BACK TO TOP

How to Add Subtitles to Your WordPress Pages and Posts

How to Add Subtitles to Your WordPress Pages and Posts

It is often the little things on your website that draw the attention of the visitors and make them stay and view your content. Those things can be something as simple as a breathtaking image, an original title, or a catchy subtitle. Content that appeals to visitors and sparks their interest means more leads and an increased likelihood of getting new readers, subscribers, sales, or conversions. So, in this article, we’ll be showing you how to add WordPress subtitles to your pages and posts.

However, this is not as simple as it might sound. WordPress webmasters have always had problems adding subtitles to pages or posts. This is because, unlike with images and titles, there isn’t a default WordPress functionality that you can use. To overcome this obstacle, some webmasters used themes that support subtitles, while others opted for solutions that involve third-party plugins and/or custom code.

We think that this topic is under-represented in the WordPress community, given its potential and appeal for visitors, so we decided to create this article. Within it, we’ll show you how to add subtitles to your WordPress pages and posts by breaking this topic down into smaller, more manageable, concepts:

How to Add Subtitles to Your Pages and Posts

The approach we’ll be taking to adding subtitles to WordPress pages and posts is by using custom code. Please note, this approach for adding subtitles is best suited for advanced WordPress users as it contains concepts that are used in object-oriented programming. Nevertheless, we will explain each part of the code we created for this article in detail so that its general purpose is clear to all. If in the end you still feel out of your depth, we encourage you to do some additional research before attempting to add WordPress subtitles to your site.

We have divided the code into two parts based on the purpose they serve. After explaining both parts, we will discuss how you can add the code to your site and what stylization adjustments it might require. Let us begin.

Creating the Subtitle Option

The first part of the code serves to create a custom section for new options and a subtitle option within that section. This code is also responsible for displaying the subtitle option on the backend of pages and posts and ensures that the value of the option is properly saved in the database.

/**
* Calls the class on the post edit screen.
*/
function call_CustomOptions() {
new CustomOptions();
}
if ( is_admin() ) {
add_action( 'load-post.php', 'call_CustomOptions' );
add_action( 'load-post-new.php', 'call_CustomOptions' );
}
class CustomOptions {
/**
* Hook into the appropriate actions when the class is constructed.
*/
public function __construct() {
add_action( 'add_meta_boxes', array( $this, 'custom_options_add_meta_box' ) );
add_action( 'save_post', array( $this, 'save' ) );
}
/**
* Adds the meta box container.
*/
public function custom_options_add_meta_box( $post_type ) {
// Limit meta box to certain post types.
$post_types = array( 'post', 'page' );

if ( in_array( $post_type, $post_types ) ) {
add_meta_box(
'qodef_custom_options_meta_box',
__( 'Custom Options', 'textdomain' ),
array( $this, 'render_meta_box_content' ),
$post_type,
'advanced',
'high'
);
}
}
/**
* Save the meta when the post is saved.
*
* @param int $post_id The ID of the post being saved.
*/
public function save( $post_id ) {
// Check if our nonce is set.
if ( ! isset( $_POST['qodef_custom_box_nonce'] ) ) {
return $post_id;
}
$nonce = $_POST['qodef_custom_box_nonce'];
// Verify that the nonce is valid.
if ( ! wp_verify_nonce( $nonce, 'qodef_custom_box' ) ) {
return $post_id;
}
/*
* If this is an autosave, our form has not been submitted,
* so we don't want to do anything.
*/
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// Check the user's permissions.
if ( 'page' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}
// Sanitize the user input.
$mydata = sanitize_text_field( $_POST['qodef_new_field'] );
// Update the meta field.
update_post_meta( $post_id, '_subtitle_value', $mydata );
}
/**
* Render Meta Box content.
*
* @param WP_Post $post The post object.
*/
public function render_meta_box_content( $post ) {
// Add a nonce field so we can check for it later.
wp_nonce_field( 'qodef_custom_box', 'qodef_custom_box_nonce' );
// Use get_post_meta to retrieve an existing value from the database.
$value = get_post_meta( $post->ID, '_subtitle_value', true );
// Display the form using the current value.
?>
<label for="qodef_new_field">
<?php _e( 'Insert a custom subtitle: ', 'textdomain' ); ?>
</label>
<input type="text" id="qodef_new_field" name="qodef_new_field" value="<?php echo esc_attr( $value ); ?>"
size="45"/>
<?php
}
}

Let us explain this code in more detail.

We’ll start by observing the simplified version of it.

function call_CustomOptions() {
new CustomOptions();
}
if ( is_admin() ) {
add_action( 'load-post.php', 'call_CustomOptions' );
add_action( 'load-post-new.php', 'call_CustomOptions' );
}
class CustomOptions {
public function __construct() {
// Code goes here
}
public function custom_options_add_meta_box( $post_type ) {
// Code goes here
}
public function save( $post_id ) {
// Code goes here
}
public function render_meta_box_content( $post ) {
// Code goes here
}
}

As we can see from this version of the code, it points to a class that we created called CustomOptions. That class has four methods: __construct, custom_options_add_meta_box, save, and render_meta_box_content. Then, we created an instance of that class using the call_CustomOptions() function. Finally, we hooked the call_CustomOptions() function onto the load-post.php and load-post-new.php hooks using the add_action() function, provided that the is_admin() conditional is fulfilled. Meaning, if you are in one of the WordPress administrative pages, an instance of the CustomOptions class will be created.

With the main idea behind the code explained, we’ll briefly clarify the purpose of each of the methods belonging to the CustomOptions class.

The custom_options_add_meta_box() function, as the name suggests, adds a meta box with the name Custom Options, but only for pages and posts. This is done using the add_meta_box() function that calls the following method for rendering the content.

That method is the render_meta_box_content(). The purpose of it is to get the subtitle value from the database using the get_post_meta() function and display it in a text field, which will have a label next to it explaining the content inserted there. We are referring to the Insert a custom subtitle: label. Additionally, this function adds a nonce field that is used for verification during the save process.

The purpose of the save()method is to perform the nonce verification and then update the appropriate database field with the subtitle that was inserted. Essentially, it saves the inserted subtitle.

WordPress uses security tokens called nonces which represent an encrypted combination of numbers and letters, generated for each user separately and only valid for a certain amount of time. These nonces are used to perform security checks after which the main part of the code is executed.

In our case, we inserted conditions that, if met, return the value of the $post_id variable, which was already supplied to the save() function. This is equivalent to not doing anything, as the main part of the code isn’t reached. The conditions we added are the following: nonce not being properly set, nonce not being valid, if an autosave of the current page or post was done, and if the current user doesn’t have the privileges for editing that page or post. After passing all those nonce verification checks, the code for saving the inserted subtitle is executed.

However, you shouldn’t forget to sanitize the subtitle value before storing it in the database. If you forget to do so, you are allowing the possibility that a user, instead of a subtitle, inserts a code that could harm the database, and by extension, your website. This is why we sanitized the value of the inserted subtitle first, using the sanitize_text_field() function, and then saved it using the update_post_meta() function.

Finally, the __construct() method is the constructor method of our CustomOptions class. Its purpose is to call the appropriate methods when an instance of the class has been created. In this case, it hooks the two methods (custom_options_add_meta_box and save) to corresponding hooks using the add_action() function.

This concludes the explanation of the first part of the code.

What we have done with this part of the code is to create a new section of options called Custom Options and a subtitle option field within that section. We also arranged for the value of the subtitle to be properly displayed in the backend of pages and posts only, as well as correctly stored in the database, after sanitization. More precisely, thanks to the save() and render_meta_box_content() methods, the subtitle value will be saved in the database and properly displayed in the field after the page updates.

Here’s how the backend of your pages and posts could look after adding the code, inserting the subtitle, and then saving the change. For specifics on how to insert the code, you can skip ahead to the subsection titled Additional steps.

Insert a custom sidebar
Blog & Magazine Themes
Behold banner
Behold

Personal Blog WordPress Theme

Buzzy banner
Buzzy

Creative Magazine Theme

Journo banner
Journo

Creative Magazine & Blog Theme

Displaying the Subtitle

The second part of the code pertains to getting the value of the previously created text field and correctly displaying it in the appropriate place on the frontend.

function display_custom_subtitle() {
/**
* Getting the current page id
* Additional conditional is to check if the current page belongs to any of the wp archive pages
* (archive, category, tag, date, etc.) and returns null
*/
$page_id = get_queried_object_id();
if ( is_archive() || is_search() || is_404() || ( is_front_page() && is_home() ) ) {
$page_id = null;
}
// Get the subtitle from the page, if that page has an existing page ID
if ( ! empty( $page_id ) ) {
$subtitle = get_post_meta( $page_id, '_subtitle_value', true );

// Display the subtitle, if inserted
if ( ! empty( $subtitle ) ) {
echo '<div class= "qodef-page-subtitle">' . $subtitle . '</div>';
}
}
}
add_action( 'lekker_action_after_page_title_inner', 'display_custom_subtitle' );

Let us take a closer look at the composition of this part of the code.

When pared down, we can see it represents a single function called display_custom_subtitle() which is hooked to the lekker_action_after_page_title_inner hook using the add_action() function.

function display_custom_subtitle() {
// Some code goes here.
}
add_action( 'lekker_action_after_page_title_inner', 'display_custom_subtitle' );

We will return to this hook later, as it is a very important part of the code. But, for now, we’ll elaborate on the content of the display_custom_subtitle() function.

First, we will store the ID of the current page or post inside the $page_id variable using the get_queried_object_id() function, which retrieves the ID of the currently queried object. However, as this function retrieves the IDs in a wider set of cases than we need (more than just pages and posts), we added a conditional that checks for the cases that we wish to exclude. It also manually sets the ID, i.e. the $page_id variable, to null (meaning non-existent). The cases we chose to exclude are the page being a WordPress archive (category, tag, date, etc.), the search page, the 404 page, and the Your latest posts page (which is the case when the homepage is set to display your latest posts in Settings > Reading).

$page_id = get_queried_object_id();
if ( is_archive() || is_search() || is_404() || ( is_front_page() && is_home() ) ) {
$page_id = null;
}

Then, as long as the $page_id has an existing ID, the remaining part of the code is executed. This includes storing the subtitle of the current page or post inside the $subtitle variable using the get_post_meta() function for the _subtitle_value meta key. Afterward, if the subtitle exists, it will be displayed on the frontend of your website using the echo function. The subtitle is wrapped with a div containing a custom CSS class called qodef-page-subtitle, which can be used to further stylize the output.

// Get the subtitle from the page, if that page has an existing page ID
if ( ! empty( $page_id ) ) {
$subtitle = get_post_meta( $page_id, '_subtitle_value', true );
// Display the subtitle, if it exists
if ( ! empty( $subtitle ) ) {
echo '<div class= "qodef-page-subtitle">' . $subtitle . '</div>';
}
}

Since we’ve covered that, we can explain the lekker_action_after_page_title_inner hook used in the last line of the code

add_action( 'lekker_action_after_page_title_inner', 'display_custom_subtitle' );

While you could simply copy and paste all the rest of the code we provided in the article, this line needs to be edited always. It contains a theme-specific hook called lekker_action_after_page_title_inner. As this hook is directly related to the Lekker theme which we are currently using, you will need to replace it with a hook that is specific to your current theme. This is something you shouldn’t overlook, as otherwise, the code for displaying the subtitle on the website’s frontend won’t work.

Simply put, hooks are a placeholder line of code that programmers leave so that others could “hook” onto it and execute some custom code without altering existing template files. In the past, WordPress users were advised to change the template files of their themes, plugins, or even WordPress itself, to add custom functionalities. However, this practice, apart from being error-prone, isn’t safe as all template files are overwritten on updates.

Therefore, this practice is no longer advised and the use of hooks is now recommended. The hooks that you use could be default WordPress hooks or those created by your theme or plugin authors. Apart from that, hooks are also divided into two types—actions and filters. The main difference between the two is that filters require a parameter to edit and then must return the edited value, whereas actions can do both, but aren’t required to do either.

We will be sticking to action hooks only in this case. To figure out the most appropriate action hook, you will need to examine the template files of your current theme, in particular the file that is responsible for creating the title or even the whole header. This is done because the expected place for a subtitle is below the code that creates the title, so the header.php file could be a good place to start. But, as the file and folder structures of themes can greatly vary, we can’t definitively suggest any files that you can look at following the header.php.

After finding the appropriate file, you will need to look at the part of its code located after the section that creates the title. Specifically, you will need to look for the do_action() function which will contain the hook you need to use. Let us illustrate using our example.

For us, the appropriate file was \wp-content\themes\lekker\inc\title\templates\title.php. We found the do_action() function directly below the part of the code that creates the title, i.e. calls the template part responsible for the title creation. As you can see on the screenshot below, the action hook that was placed inside the do_action() function was lekker_action_after_page_title_inner. Therefore, this is the exact action hook we used to “hook” onto using the add_action() function in the last line of our code.

Code that creates

You will need to do a similar thing on your end, as well. After figuring out the appropriate action hook, you will need to insert it in the call of the add_action() function. Meaning, instead of our last line of code, you will need to add the following:

add_action( 'name-of-your-action-hook', 'display_custom_subtitle' );

Please note, the part with name-of-your-action-hook should be replaced accordingly.

Additional Steps

After making the necessary adjustment(s) to the code shown in the previous subsection, the next step is inserting it into your theme’s functions.php file or inside a site-specific plugin. We will show you the steps required for the former. As this will require the use of FTP, we suggest brushing up on your knowledge of it. We also advise making a backup of your website as a safety precaution. When you’ve done all that, we can begin.

First, connect to your server using your FTP credentials and navigate to your root WordPress directory, often called public_html.

Root WordPress directory

Then, navigate to /wp-content/themes, find the directory of your current theme and click on it. Locate the functions.php file within the directory, right-click on it and select the View/Edit option.

Find the directory of your current theme

Open the file using a text editor and add both parts of the code at the end of the file, one below the other. You can see below how it looks. However, since the code with comments is a bit long, we have shown it across three screenshots with the appropriate code line navigation on the left.

Add Subtitles to Your WordPress code 1
Add Subtitles to Your WordPress code 2
Add Subtitles to Your WordPress code 3

After adding all the code, save the changes you made and upload the file back to your server to overwrite the old version of it.

Then, you will need to open a page on your website, insert a subtitle through the meta field that was created, save it and check how it is displayed on the website. In some cases, the display of the subtitle won’t match the current stylization of your website. If that happens to you, you will need to create some additional CSS code that adjusts the stylization of the subtitle. To help with that, you can use the custom class that was added to the div element that wraps the subtitle, which we mentioned earlier. Meaning, you can add your CSS code in the form given below.

.qodef-page-subtitle {
// Insert CSS rules here
}

Since creating the appropriate code is done on a case-by-case basis, we can’t provide any universally applicable CSS. Instead, we will share the CSS that we used to further stylize our example code.

.qodef-page-subtitle {
position: relative;
left: 0;
top: -40%;
display: inline-block;
font-family: Poppins,sans-serif;
font-weight: 500;
color: white;
z-index: 100;
}

After inserting this CSS, we got the output shown in the screenshot below.

Lakker title

As a final piece of advice, since we needed only a little bit of CSS to adjust the stylization, we placed it inside the Appearance > Customize > Additional CSS field. However, if you require larger quantities of CSS to stylize your WordPress subtitles, then creating a separate CSS file and enqueueing it using the wp_enqueue_style() function is the recommended programming practice.

Final Thoughts

Adding WordPress subtitles to your pages and posts can be achieved using specific themes, plugins, or code. In this article, we focused on showing you how to add subtitles by using a custom field that we created. Even if you aren’t experienced in writing code, you can still copy and paste the example we provided. Furthermore, the explanations that accompany the code should help you understand which part(s) should and shouldn’t be edited, as well as how you can do so.

Moreover, the process of adding a custom feature such as a subtitle could be a good exercise for any users that aspire to become successful WordPress developers. And this article could serve as an excellent how-to guide on adding a new feature to your website using user-created custom fields. For this reason, we wholeheartedly advise bookmarking the article for further re-reading and use.

Post your comment

Comments0