WordPress Theme Tutorial for Beginners – Part 11: Custom Page Templates

In this lesson of WordPress theme tutorial for beginners we learn about page templates, what they are, how to create them and best practices. We’ll make a fullwidth template as an example. Along the way we also add a class to body by asking if the page is using a specific page template.

What are page templates

Page templates are useful for cases where you want a different layout or setup for a specific page. Common examples of page templates usages are listing out posts in a custom post type (e.g. portfolio, books, or services), having a completely different content or layout (e.g. inside columns), or even simply making a page fullwidth (no sidebar).

The usability of page templates have lessened after WordPress version 5.x (Gutenberg). The new Gutenberg editor allows for great flexibility to build such pages without the need of page templates. Regardless, we will learn how to add a custom page template into our theme.

Inside the metabox “Page Attributes” for pages is where the choice of page template appears. But the template option will only appear if the active theme have at least one page template.

Page templates can actually be used for posts and custom post types too. After WordPress 4.7 and up, you can define which post types you want the template to be available to. WordPress will automatically add the required “Page Attributes” metabox to those post types.

Page template naming and placement

To start off you would usually make a copy of whatever template file is closest to what you want to achieve with the page template. In most cases it’s page.php. As for the naming of your page template it’s kind of up to you. But there are some rules and some common sense.

It’s tempting to simply name your page template e.g. page-books.php for a template listing out a custom post type books. Never prefix your page template with ‘page-‘! If you remember from WordPress’ template hierarchy, WordPress will look for page-<slug>.php before it attempts page.php, and users of your theme might encounter unexpected behaviour.

A good practice is prefixing your page template with something that’s not part of WordPress’ page template names. For example ‘pagetemplate-', ‘pt-‘, or simply just the full name ‘fullwidth-template.php‘. It’s also good practice to keep them in a subfolder; /page-templates/ however this is not good if you want your theme to be available to extend with a child theme. A child theme cannot override page templates that are placed in a subfolder in the parent theme.

Once you have decided for a naming pattern, let’s go ahead and create a page template.

Creating a page template

Make a copy of page.php and rename it to pagetemplate-fullwidth.php. To make it into a page template, you need only add a comment at the very beginning which tells WordPress that this is a page template:

pagetemplate-fullwidth.php
<?php 
/*
Template Name: Fullwidth 
*/
get_header(); ?>
<?php 
if (have_posts()) {
...

All you need is a comment at the very beginning of the file, with “Template Name: ” and your template name after it. That’s it! Go into admin, edit a page, and you should see the option to choose “Fullwidth” as a template.

I did mention that in WordPress 4.7 you can define which post types you want the page template to be available for. Right now it’s only available for pages, but say you want the option to make posts fullwidth as well? In that case, add “Template Post Type: ” inside the same comment block and define your post types separated by comma. For example, to make it available for both posts and pages;

pagetemplate-fullwidth.php
<?php 
/*
Template Name: Fullwidth 
Template Post Type: post, page
*/
get_header(); ?>
<?php 
if (have_posts()) {
...

Edit a post and you should see a new metabox “Post attributes” where you can choose Fullwidth template. Nice!

Changing the code in our page template

Now let’s edit the page template so it actually does something different than the single page view. Let’s remove the request for sidebar template: (I commented it out to make it more visible, but you can just delete the line).

pagetemplate-fullwidth.php
...
	?><p><?php _e('No posts, sorry.', 'wptutorial'); ?></p><?php
}
//get_sidebar(); 
get_footer(); ?>

Let’s do one more thing to make our page template more easier to style. When you add CSS, you often need to know if the page has a sidebar or not, in order to adjust the columns/layout. Remember body_class which provides a whole bunch of useful classes to the body element? What if we added a custom class onto body that tells us if the current page has a sidebar or not?

Filter on body_class

Note: You might have noticed that any page or post that use a page template already gets a specific body class; “page-template-<name-of-file>” – in our example "page-template-pagetemplate-fullwidth". It’s a pretty long class, and besides, we want to make our theme more flexible – and allow fullwidth on other templates apart from the ones using page template. For example you usually don’t want a sidebar on the front page, right?

Note: This only adds a class to the body so styling gets easier, it doesn’t actually disable the sidebar output. You have to remember to delete the get_sidebar() wherever you won’t want it.

Let’s add a filter for body_class for adding a custom sidebar class in our functions.php, so that you can later add more to it in other cases you don’t want the sidebar. WordPress has a nice conditional tag for checking if a page template is in use; is_page_template() where you put your page template name as parameter. We want to add a class if this is not true, so we add the reverse with “!”:

functions.php
add_filter('body_class', 'wptutorial_body_class_filter');
function wptutorial_body_class_filter($classes) {
	if (!is_page_template('pagetemplate-fullwidth.php')) {
		$classes[] = 'has-sidebar';
	}
	return $classes;
}

Most likely while you are developing the templates, you will occasionally run into templates you don’t want to add the sidebar class to, and as you go add those cases inside this if. For example if you don’t want the sidebar class on the frontpage, you can add !is_front_page(). This will add the class ‘has-sidebar’ to all pages except frontpage and the page template:

if (!is_front_page() && !is_page_template('pagetemplate-fullwidth.php'))

It’s up to you how many page templates you want and what they should contain. This was just a simple introduction. If you are interested in how to query other posts inside a page templates, take a look at the next step.

Leave a comment