BACK TO TOP

How to Create Custom Single Post Templates in WordPress

How to Create Custom Single Post Templates in WordPress

A theme’s template files are the backbone of your WordPress website—they serve to display various kinds of dynamic content on the website. While most WordPress users only rely on these templates and page builders to edit their content, there is another way to customize your website content. And it involves writing custom template files using code. In this article, we will discuss how you can build custom post templates specifically, and consider the potential benefits of doing so. And we’ll show you how to tackle this topic by breaking it down into several smaller steps:

Why you would want to create custom single post templates in WordPress

Custom post templates are best applied on specific posts that are meant to stand out from the rest of your website and wow the audience. They offer you the ability to create unique, completely custom, layouts, which can be beneficial for a wide range of websites and occasions.

For example, you can use custom post templates for posts that belong to a trending category or posts made by specific guest authors or contributors. Moreover, you can create specific post templates for each author on your website, making their content visually recognizable. You can even create templates for specific post types, especially if you’ve added any custom post types. These are only a few examples to give you an idea of the range of possibilities offered by creating WordPress single post templates.

Simply put, custom post templates allow you to create a layout that isn’t otherwise available through your theme or the use of page builder plugins. By knowing how to code them, you will gain more flexibility for customizing your website content.

Qode Themes: Top Picks
Bridge New Banner
Bridge

Creative Multi-Purpose WordPress Theme

Stockholm WordPress Theme
Stockholm

A Genuinely Multi-Concept Theme

Startit WordPress Theme
Startit

Fresh Startup Business Theme

How to create custom single post templates in WordPress

Now that you have a clearer picture of the benefits involved in making custom post templates, let’s take a look at how you can do so. We divided this part of the article into two sections. One covers the requirements you need to know before you start coding, and the other illustrates how a custom template can look using an example we created.

Understanding the template file hierarchy

As we mentioned at the start, template files are in charge of displaying various pieces of dynamic content on your website. For them to work properly, a strict Template Hierarchy structure must be observed. WordPress automatically checks whether a page or post has a custom template assigned to it before using any of the template files provided by your theme.

In the past, this was only true for pages (i.e. page templates), but the functionality was extended to posts and custom post types starting with the WordPress 4.7 update. As such, the current hierarchy for posts and custom post types is the following:

  • custom page/post template file
  • single-{post-type}-{post-slug}.php
  • single-{post-type}.php
  • single.php
  • singular.php
  • index.php

Let’s clarify what this means.

Firstly, the {post-type} notation represents the slug of a specific post type, while the {post-slug} represents the slug of a specific post item. The files with names that contain the {post-type} notation will only apply to custom post types, which are registered using the register_post_type() function. For example, if you registered a custom post type with portfolio-item as its slug, then a file within this hierarchy would be named single-portfolio-item.php.

Secondly, a custom template file is the only one that doesn’t have to follow the strict naming conventions shown above. We deliberately put page/post as part of the name to emphasize that custom template files can be written for pages, posts, and custom post types in a uniform way. This was also part of the WordPress 4.7 update that we mentioned earlier.

The reason for this flexibility of use lies in the template header, which is the first part—and a mandatory one—every custom template file. It serves to register the template and give some additional information about it. The template header is, in fact, a simple comment that specifies the template name which post type, or types, it was written for.

The template header has a strict structure; the relevant pieces of information are specified after the Template Name: and Template Post Type: strings. No other information is required, but if you choose to add some, it can be helpful for anyone reviewing the file. Also, since the template file has the .php extension, it has to begin with the opening PHP tag: <?php. However, the closing PHP tag (?>) can be placed later in the code, depending on the main content of the file.

Having explained that, you can see an example of how a custom template file could start below.

<?php
/**
* Template Name: No Sidebar Template
* Template Post Type: post, page
*/

Using this template header, you can register a custom template called No Sidebar Template and make it available for both posts and pages. That means that No Sidebar Template will appear as an option both in Page Attributes on a single page, as well as in Post Attributes on a single post.

Page Template No Sidebar
Post Template No Sidebar

As we are focusing on WordPress single post templates in this article, we will be setting the template post type in our example to post. Other than that, our final piece of advice on template headers would be to use self-explanatory names as it will help you avoid any possible confusion later on.

With that being said, there are a few other things we need to mention before moving on to the example we made for the article.

First, in terms of code, there are a lot of things that could be added to a custom template file. These are all added within the second part of a template file, the one that creates the content. They include codes that display the sidebars, widgets, content inserted via the editor, custom post type meta info, and so on.

There are a lot of different layouts that can achieve using custom template files if you possess the appropriate programming skills. And even if you don’t, there’s no reason for you to start from scratch—custom template files are most commonly made by taking an appropriate template file from your theme and modifying it to your preference.

After creating the complete template file, you should save it as a .php file and upload it to your server. Using FTP, you should place the file into one of the four appropriate places for custom template files. Those are the active parent theme directory, active child theme directory, or a subdirectory within either of those two locations.

Additionally, you should take care when naming the file. Avoid using any of the already reserved names (e.g. index, archive, single,…) or names that contain an already reserved prefix (e.g. single-, archive-, page-,…). For simplicity’s sake, you might want to name the file the same as the template, so you can keep track of it easily.

Creating custom single post templates

In the following section, we will be discussing how to create custom post layouts using custom code. As this process requires a significant familiarity with WordPress and previous coding experience, it is more inclined towards intermediate and advanced WordPress users. We’ve provided detailed explanations and helpful links to clarify the subject matter, but we urge you to do more research if you need to before proceeding.

The process of creating a WordPress single post template also requires an understanding of how to use FTP, as you’ll need it for uploading the .php file to the server after you’ve created the code. Also, before going further, we advise you to make a backup of your website just in case.

Even though the requirements for this method might seem high, the upside is significant—you’ll be able to make a custom post layout perfectly matched to your needs. And to help you in this process of making WordPress single post templates, we prepared a code example for this article. You can use it as is or modify it as you see fit.

With that being said, let’s take a look at the code itself.

<?php
/*
* Template Name: No Sidebar Post Template
* Template Post Type: post
*/
get_header();
?>
<main id="main-content" class="custom-grid">
<div class="custom-grid-inner">
<?php if ( have_posts() ) {
while ( have_posts() ) {
the_post();
$author_id = get_the_author_meta( 'ID' );
$author_url = get_author_posts_url( $author_id );
?>
<article <?php post_class( 'custom-blog-item' ); ?>>
<div class="blog-item-inner">
<h1 itemprop="name" class="bi-title entry-title">
<?php the_title(); ?>
</h1>
<div class="content-above-image">
<div class="bi-author">
<div class="bi-author-avatar">
<a itemprop="url" href="<?php echo esc_url( $author_url ); ?>">
<?php echo get_avatar( $author_id, 60 ); ?>
</a>
</div>
<div class="bi-author-name">
<a itemprop="author" class="bi-author-link"
href="<?php echo esc_url( $author_url ); ?>">
<?php the_author_meta( 'display_name' ); ?>
</a>
</div>
</div>
<div class="bi-category">
<?php the_category( ' / ' ); ?>
</div>
</div>
<div class="image-wrapper">
<?php if ( has_post_thumbnail() ) { ?>
<div class="bi-media-image">
<?php the_post_thumbnail( 'full' ); ?>
</div>
<?php } ?>
<div class="bi-date">
<div itemprop="dateCreated" class="entry-date updated">
<?php the_time( get_option( 'date_format' ) ); ?>
</div>
</div>
</div>
<div class="content-below-image">
<?php if ( get_the_tags() ) { ?>
<div class="bi-tags">
<h5 class="bi-tags-label"><?php esc_html_e( 'Tags: ', 'domain_name' ); ?></h5>
<div class="bi-tags-wrapper">
<?php the_tags( '', ', ', '' ); ?>
</div>
</div>
<?php } ?>
<div class="article-text">
<?php
// Include post content
the_content();
?>
</div>
<?php
// Previous/next post navigation.
the_post_navigation(
array(
'next_text' => '<span class="nav-label">' . esc_html__( 'Next article', 'domain_name' ) . '</span><p class="next-post-title">%title</p>',
'prev_text' => '<span class="nav-label">' . esc_html__( 'Previous article', 'domain_name' ) . '</span><p class="previous-post-title">%title</p>'
)
);
// Include comments
if ( comments_open() ) { ?>
<div class="comment-section">
<?php comments_template(); ?>
</div>
<?php } ?>
</div>
</div>
</article>
<?php } // End of the loop.
}
wp_reset_postdata(); ?>
</div>
</main>
<?php
get_footer();

To make this code easier to grasp, we’ll explain its main components.

We’ll do that by looking at a more simplified version of the code first. As you can see from the template header below, the code represents a blog post-specific template called No Sidebar Post Template.

Apart from that, the code contains a tiny piece of HTML markup that wraps a WordPress Loop. The main part of the code, which specifies what is shown on a given post, is located within it.

Furthermore, the code contains the use of the get_header() and get_footer() functions, which load the header and footer templates of the site’s currently active theme. Besides them, we also used the wp_reset_postdata() function to reset the global $post variable to the current post in the main query.

<?php
/*
* Template Name: No Sidebar Post Template
* Template Post Type: post
*/
get_header();
?>
<main id="main-content" class="custom-grid">
<div class="custom-grid-inner">
<?php if ( have_posts() ) {
while ( have_posts() ) {
the_post();
// Post content code goes here
} // End of the loop.
}
wp_reset_postdata(); ?>
</div>
</main>
<?php
get_footer();

Now, let’s focus on the main part of the code.

First, we have defined two variables—the $author_id and the $author_url. They are used to display the post author’s avatar and to link it to the appropriate post author archive page. As the variable names indicate, they contain the post author’s ID and URL and are created using the functions get_the_author_meta() and get_author_posts_url().

$author_id = get_the_author_meta( 'ID' );
$author_url = get_author_posts_url( $author_id );

Following that, we come to the content of every post, wrapped with an <article> tag. First, the post title is shown using the the_title() function. Then there are three distinct sections—the section with the post’s featured image and the parts directly above and below it. If added to the post, the featured image is shown in its original size using the the_post_thumbnail() function. This section also contains the post’s publish date. As for the two sections surrounding it, they contain a bit more content, which we will briefly cover below.

 <article <?php post_class( 'custom-blog-item' ); ?>>
<div class="blog-item-inner">
<h1 itemprop="name" class="bi-title entry-title">
<?php the_title(); ?>
</h1>
<div class="content-above-image">
<!-- Content above image code goes here -->
</div>
<div class="image-wrapper">
<?php if ( has_post_thumbnail() ) { ?>
<div class="bi-media-image">
<?php the_post_thumbnail( 'full' ); ?>
</div>
<?php } ?>
<div class="bi-date">
<div itemprop="dateCreated" class="entry-date updated">
<?php the_time( get_option( 'date_format' ) ); ?>
</div>
</div>
</div>
<div class="content-below-image">
<!-- Content below image code goes here -->
</div>
</div>
</article>

The section above the image contains two distinct parts. The first is the author’s avatar image and name. The second is a list of categories, separated with a forward slash (/), that the post belongs to. Additionally, both the author’s avatar image and name link to the author archive page, and the categories link to their respective category archive pages.

<div class="content-above-image">
<div class="bi-author">
<div class="bi-author-avatar">
<a itemprop="url" href="<?php echo esc_url( $author_url ); ?>">
<?php echo get_avatar( $author_id, 60 ); ?>
</a>
</div>
<div class="bi-author-name">
<a itemprop="author" class="bi-author-link"
href="<?php echo esc_url( $author_url ); ?>">
<?php the_author_meta( 'display_name' ); ?>
</a>
</div>
</div>
<div class="bi-category">
<?php the_category( ' / ' ); ?>
</div>
</div>

As for the section below the featured image, it contains four distinct parts. The first among them is the Tags: label followed by a list of tags, which are separated with commas(,) that the post belongs to. Next, the part that can be directly edited using your page builder/editor of choice is added to the post, using the the_content() function. Then, using the the_post_navigation() function, the default WordPress post navigation for Previous/Next post is added. We also specified the HTML markup of the Previous/Next links. And, if the post has comments enabled, a comment template will be displayed at the end of the post, using the comments_template() function. Finally, according to WordPress standards, we properly sanitized the code in various places throughout it.

<div class="content-below-image">
<?php if ( get_the_tags() ) { ?>
<div class="bi-tags">
<h5 class="bi-tags-label"><?php esc_html_e( 'Tags: ', 'domain_name' ); ?></h5>
<div class="bi-tags-wrapper">
<?php the_tags( '', ', ', '' ); ?>
</div>
</div>
<?php } ?>
<div class="article-text">
<?php
// Include post content
the_content();
?>
</div>
<?php
// Previous/next post navigation.
the_post_navigation(
array(
'next_text' => '<span class="nav-label">' . esc_html__( 'Next article', 'domain_name' ) . '</span><p class="next-post-title">%title</p>',
'prev_text' => '<span class="nav-label">' . esc_html__( 'Previous article', 'domain_name' ) . '</span><p class="previous-post-title">%title</p>'
)
);
// Include comments
if ( comments_open() ) { ?>
<div class="comment-section">
<?php comments_template(); ?>
</div>
<?php } ?>
</div>

With this, we covered all the major components of the code example prepared for the article.

As we mentioned in the previous section, to use this code, you will need to save it as a .php file and upload it to your server, into one of the four appropriate locations. Afterward, you will need to edit one of your posts, assign the No Sidebar Post Template to it, and review the results.

Even though most of the hard work is already done, at this point you might need some additional CSS code for stylization purposes. This is a principle that also applies when you’re adding a new feature or functionality using custom code snippets.

CSS code used for stylization is made on a case-by-case basis. As such, we can’t provide you with an example that would apply to all WordPress websites. Instead, you need to create the appropriate CSS code on your own, so that you are sure it will match your current website design.

Below, you can find the CSS we created for our new WordPress single post template. We have to caution you one last time against simply copy-pasting it as there are no guarantees that this style will fit with your site.

#main-content{
padding: 10px 0 30px;
}
.content-above-image {
position: relative;
margin-bottom: 20px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
}
.bi-author{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
font-size: 18px;
}
.bi-author-avatar img{
border-radius: 50px;
-ms-flex-negative: 0;
flex-shrink: 0;
margin-right: 15px;
}
.image-wrapper {
position: relative;
}
.bi-date {
position: absolute;
top: 16px;
left: 16px;
padding: 12px;
color: #000;
font-size: 18px;
background: #fcd4d2;
}
.bi-tags {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
.bi-tags-wrapper{
padding-left: 18px;
}
nav.navigation.post-navigation {
margin-top: 40px;
}
.nav-links{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
text-align: center;
padding: 12px 0;
background: #f7f7f7;
}
.nav-previous, .nav-next {
padding: 8px 15px;
background: #fcd4d2;
border-radius: 20px;
}
.nav-previous p, .nav-next p {
margin: 0;
}

CSS code like this can be added via your dashboard in Appearance > Customize > Additional CSS. Alternatively, you can insert it using a WordPress plugin that allows you to add CSS snippets; but make sure to test the plugin first to verify that there are no compatibility issues with your website.

Our more advanced readers can also add the CSS code by putting it in a separate .css file, uploading it to the server, and enqueueing it using wp_enqueue_style(). For more information on this topic, you can take a look at our article on enqueueing custom scripts and stylesheets.

Finally, after adding all the code, we need to review the result. You can see ours on the screenshots below.

Result Post Template
Result Post Template

Final Thoughts

Custom post templates can help you achieve tailor-made designs that otherwise wouldn’t be possible using only templates provided by your theme or with page builders. Knowing how to create WordPress single post templates can help your blog to stand out and be more engaging for your readers.

Custom template files can be made relatively easily by adding a template header and the appropriate code for displaying the main content. To help you along with this process, we designed an example single post template and shared its code, and took care to explain it along the way. Also, we touched on the potential stylization your new template might require and the methods for adding it to your site. Given all of that, we are confident that you will be able to create your own custom WordPress single post template.

Post your comment

Comments0