Template Parts

Let’s discuss template parts and your Theme Blvd child theme. There’s a lot of power and flexibility here.

  1. Introduction — The template parts concept explained.
  2. Customizing Default Template Parts — The easiest way to customize; just copy the files to your child theme.
  3. Changing Which Template Part Files Are Called — Getting more complex. Adding new, custom template part files.
  4. In-Depth Example: Custom Post Types — All about how you can create template parts for custom post types, and make it dynamic.

Introduction

If you’re using a theme with Theme Blvd Framework prior to 2.5, see the older version of this article, Template Parts (legacy).

Working with a theme framework like ours that utilizes action hooks to control just about everything can provide you with a completely dynamic child theme development experience. With that said, among some other more complex themes advertised as “frameworks” I feel that there is a certain element that becomes lost in this process. And that’s the luxury of actually getting a look at your HTML markup and WordPress theme tags outside of deeply-hooked PHP functions.

When opening a standard theme file within the Theme Blvd framework to see how it’s constructed (i.e. page.php, single.php, archive.php, etc.), it’s nice to be presented with something we’re all familiar with in the basics of WordPress theme development. To do this meant the outer HTML markup had to be crafted just right to give you the most flexibility from your child theme, while still keeping most items hooked within.

And so while these common top-level theme files are not intended to be edited, it is at least possible, as a last resort. Also, this allows us to get a visual representation of the outer theme structure, without having to just inspect our live website in the web browser.

So, then what files are we intended to edit?

And this question brings us to our big point – As a WordPress theme developer, you shouldn’t completely lose the ability to work with some basic HTML and WordPress theme tags. With our framework, you can forget about copying and pasting the same wrapping HTML code into the common theme files like page.php, single.php, etc, and instead just work with the template parts nested within the core of the standard theme files.

These template parts are going to smaller files with less code, that are easier to manage, allowing you to edit more specifically the area you want, without dragging all the outer stuff with them.

Customizing Default Template Parts

The table below outlines the default template files of Jump Start 2. If you’re using another theme with Theme Blvd Framework 2.5+, there may be slight variations, but it’ll be more-or-less the same.

Working within the scope of the template part files that already exist, it’s very easy to make changes. Simply copy the default files from the parent theme directory to your child theme and make your edits. Just make sure these files are placed within your child theme in a directory named /template-parts, maintaining the same structure as the parent theme.

File Description
/template-parts/content.php Single post and individual post of a blog
/template-parts/content-404.php 404 (not found) page
/template-parts/content-attachment.php Single attachment post
/template-parts/content-blog.php Individual post of a blog display
/template-parts/content-featured-archives.php “Epic Thumbnails” (full-width and full-screen banner) for archives.
/template-parts/content-featured-wc.php “Epic Thumbnails” (full-width and full-screen banner) for WooCommerce pages.
/template-parts/content-featured.php “Epic Thumbnails” (full-width and full-screen featured image) for standard pages.
/template-parts/content-footer.php Website footer content.
/template-parts/content-grid.php Individual post of a post grid
/template-parts/content-head.php Website <head> and call to wp_head().
/template-parts/content-header.php Website header content.
/template-parts/content-list.php Individual post of a post list
/template-parts/content-mini-grid.php Individual post of a mini post grid
/template-parts/content-mini-list.php Individual post of a mini post list
/template-parts/content-mobile-header.php Website mobile header content.
/template-parts/content-mobile-panel.php Website mobile panel with navigation.
/template-parts/content-page.php Static page, with default page template
/template-parts/content-panel.php Website side panel content (if enabled).
/template-parts/content-page-search.php Wrapping content of search results
/template-parts/content-search-result.php Individual post in a search results list
/template-parts/content-showcase.php Individual post in a post showcase
/template-parts/content-small-grid.php Individual post in a small grid.
/template-parts/content-small-list.php Individual post in a small list.
/template-parts/content-sticky-header.php Website sticky header content (if enabled).
/template-parts/content-template-archives.php Content of “Archives” page template
/template-parts/content-template-sitemap.php Content of “Sitemap” page template

Changing Which Template Part Files Are Called

As you dig deeper, you may find that want to call your own custom template parts for different scenarios. This is possible with the way the framework calls get_template_part() (a default WordPress function), and how we filter the values passed to it.

Note: Are you trying to just change the entire post display for a post archive? For example, maybe you want your archives to display posts in a grid, instead of a blog. This wouldn’t involve changing the template part; instead, see Archive Post Displays.

Identifying the Template Part ID

In order to create custom template parts, you need to first know the ID the framework uses for the template part you want to target. This will be needed later when you filter in your template part from your child theme’s functions.php.

Header

ID Default Value Resulting File
head head /template-parts/content-head.php
header header /template-parts/content-header.php
mobile_header mobile-header /template-parts/content-mobile-header.php
sticky_header sticky-header /template-parts/content-sticky-header.php

Footer

ID Default Value Resulting File
footer footer /template-parts/content-footer.php

Blog and Single Posts

ID Default Value Resulting File
blog blog /template-parts/content-blog.php
blog_paginated blog /template-parts/content-blog.php
single single /template-parts/content-single.php
attachment attachment /template-parts/content-attachment.php
featured featured /template-parts/content-featured.php
featured_wc featured-wc /template-parts/content-featured-wc.php
featured_archives featured-archives /template-parts/content-featured-archives.php

Notes: Because content-single.php don’t exist, the default content.php file is called. So if you wanted to separate the display of blogroll posts vs the single post, you could simply create these files in your child theme, and they’ll automatically take effect.

Post Grids

ID Default Value Resulting File
grid grid /template-parts/content-grid.php
grid_paginated grid /template-parts/content-grid.php
grid_mini mini-grid /template-parts/content-mini-grid.php

Notes: Here we can see that (by default), whether a post grid is paginated or not, it will use content-grid.php. And for a mini post grid, content-mini-grid.php is used.

Post Lists

ID Default Value Resulting File
list list /template-parts/content-list.php
list_paginated list /template-parts/content-list.php
list_mini mini-list /template-parts/content-mini-list.php

Notes: Here we can see that (by default), whether a post list is paginated or not, it will use content-list.php. And for a mini post list, content-mini-list.php is used.

Post Showcase

ID Default Value Resulting File
showcase showcase /template-parts/content-showcase.php
showcase_paginated showcase /template-parts/content-showcase.php

Notes: Here we can see that (by default), whether a post showcase is paginated or not, it will use content-showcase.php.

Pages

ID Default Value Resulting File
page page /template-parts/content-page.php
naked_page page /template-parts/content-page.php
404 404 /template-parts/content-404.php
search page-search /template-parts/content-page-search.php
search_results search-result /template-parts/content-search-result.php

Notes: The search ID is used for the template to construct the outer wrap around the search results list, while the search_results ID is used for the individual posts that get displayed within the search results list.

Panels

ID Default Value Resulting File
panel panel /template-parts/content-panel.php
mobile_panel mobile-panel /template-parts/content-mobile-panel.php

Notes: When dealing with a standard page, we can see that whether we use the “Default” page template or apply the “Naked Page” page template, by default the same file content-page.php is used.

Changing the Template Part ID

Now that you’ve identified the template part ID that corresponds to what you want to change, you can filter in a new value that corresponds to how you name your new custom template part file. To do this, you can take advantage of the themeblvd_template_part filter, which is applied every time a template part is called.

This filter is applied on the $part value, with the additional parameter $id passed in.

function my_template_part( $part, $id ) {

	if ( 'page' == $id && is_page( 'my-page' ) ) {
		$part = 'my-page';
	}

	return $part;

}
add_filter( 'themeblvd_template_part', 'my_template_part', 10, 2 );

In the snippet above, we’re changing the template part used for a specific page to use a custom file called content-my-page.php.

  • Because this filter is applied to all template parts, I first wrote a condition to check that $id was equal to the ID I wanted to target, which was page.
  • Then I made sure it’s loading on the specific page with is_page( 'my-page' ).
  • When these two conditions are true, I’m setting $part to my-page.
  • And finally, I returned the $part value back, whether it’s been changed or not. In general, any time you’re adding a filter, always remember that you must return a value back, whether you’ve changed it or not.

Create Your Template Part File

And lastly, you need to create the template file you’ve referenced and put it in the template-parts directory of your child theme. It will be named in the content-{$part}.php format.

So, in reference to the previous code snippet, we’d now create a file on our child theme, /template-parts/content-my-page.php. It will now be used to display the content of that specific page.

In-Depth Example: Custom Post Types

Let’s now look at a more complex example that many people ask about, where we can break down everything we’ve learned in this article.

Note: Feel free to skip to the code.

Setting up the Scenario

The most popular scenario I get asked about when dealing with template parts is with custom post types. For example, let’s say we want to create a custom post type for Books, which we’ve registered as book.

After you’ve created your post type for Books, you’ll see that the framework is using the default content.php to display the content of each book post, which is going to match your standard posts. But I’m guessing you’ve made it this far in the article because you want something different to display!

What You Probably Want to Do, but Shouldn’t

Well, if you’re experienced with WordPress theming, your first instinct is going to copy the theme’s single.php file to your child theme, rename it to single-book.php, and start editing away. STOP!

This is the point in the process where you stop what you’re doing and bear with me. In most generic themes, yes this is what you would probably do. And if you wanted to do this with your Theme Blvd theme, you absolutely could. But, I’m here to tell you there’s a better, less messy way.

Why would this be messy? — What happens if the next update to the theme, we make some slight structural HTML change that effects single.php? When you update, it will be fairly time-consuming to identify this change and incorporate it back in to the file in your child theme.

This is why we separate out the content into a separate file. This separate file — i.e. the “template part” — is smaller, easier to read, and will contain less code to manage.

Code to Filter in a New Template Part for Custom Post Types

The Single Post

Okay, first let’s keep it simple, and continue to expand on our code. When a single post of type book is displayed, we want to use a file called content-book.php in our child theme.

So, let’s filter this in from our child theme’s functions.php. From the tables above, we can identify that the ID of the template part we’re targeting is single.

function my_template_part( $part, $id ) {

	// "Book" single posts
	if ( 'single' == $id && 'book' == get_post_type() ) {
		$part = 'book';
	}

	return $part;

}
add_filter( 'themeblvd_template_part', 'my_template_part', 10, 2 );

Now, you just need to create an actual file /template-parts/content-book.php in your child theme. The fastest way to get started with this would probably just be to copy /template-parts/content.php to your child theme from the parent theme and rename it — then start editing it.

Posts in Different Scenarios

Because our filter is applied to ALL template parts, we can begin to get sucked down a rabbit hole of possibilities. Previously, we identified the single post, but what about when a Book is displayed in other post displays?

For example, maybe want to set up a post grid of books, but we want them to display differently than standard posts would in a grid. From the tables above, we can see that grid and grid_paginated are the two ID’s we need to target. So, let’s create a file /template-parts/content-grid-book.php.

Sure, we could write out a whole new function and filter it onto themeblvd_template_part, but it might be more efficient to just handle all this in a single function, expanding on what we’ve already written above.

function my_template_part( $part, $id ) {

	if ( 'book' == get_post_type() ) {

		// "Book" single posts
		if ( 'single' == $id ) {
			$part = 'book';
		}

		// "Book" post grid
		if ( 'grid' == $id || 'grid_paginated' == $id ) {
			$part = 'grid-book';
		}
	}

	return $part;

}
add_filter( 'themeblvd_template_part', 'my_template_part', 10, 2 );

Multiple Post Types, a More Dynamic Way

All right, so what happens when you start adding multiple post types? You’ve got Books. Now what happens when you add Movies (post type: movie) and Songs (post type: song)?

I guess we could copy out the above code three times, change the values, and call it a day. But instead, let’s start to think more efficiently. Let’s set up a system that will handle all three post types, and any we add in the future.

Let’s set it up like this: All custom post types will use a file content-{post_type}.php for single posts and content-grid-{post_type}.php when those posts are in a post grid.

function my_template_part( $part, $id ) {

	// All custom post types
	if ( 'post' != get_post_type() ) {

		// Single posts
		if ( 'single' == $id ) {
			$part = get_post_type();
		}

		// Post grid
		if ( 'grid' == $id || 'grid_paginated' == $id ) {
			$part = 'grid-' . get_post_type();
		}
	}

	return $part;

}
add_filter( 'themeblvd_template_part', 'my_template_part', 10, 2 );

Note: When we use the condition 'post' != get_post_type(), we’re checking that it’s any post type that’s not the WordPress standard post type. And since the framework calls pages and attachments (also WordPress post types) separately, we don’t have to worry about those.

So, the above code snippet will create our dynamic system. Now, we just need to make sure to create the corresponding files in our child theme for all of these post types we’ve registered.

  1. /template-parts/content-book.php
  2. /template-parts/content-grid-book.php
  3. /template-parts/content-movie.php
  4. /template-parts/content-grid-movie.php
  5. /template-parts/content-song.php
  6. /template-parts/content-grid-song.php