WordPress Template Hierarchy in Depth
Learning Objectives
- Master the WordPress Template Hierarchy decision tree
- Understand how WordPress selects templates for different content
- Learn the priority order of template files
- Use conditional tags to control template logic
- Create specialized templates for specific content types
- Debug template loading issues effectively
Introduction
The WordPress Template Hierarchy is like a detailed roadmap that WordPress follows to decide which template file to use. Think of it as a sophisticated decision tree - WordPress starts at the top with the most specific template and works its way down to more general ones until it finds a file that exists.
Understanding the Hierarchy
The template hierarchy is WordPress's way of being flexible yet predictable. It's like having multiple backup plans:
Complete Template Hierarchy Map
WordPress checks for templates in this specific order:
(e.g., page-about.php)
(e.g., page.php)
(index.php)
Homepage Display Hierarchy
The homepage has its own special hierarchy depending on your Settings β Reading configuration:
-
1
front-page.php
Always used for the front page if it exists, regardless of settings -
2
home.php
Blog posts index, whether on homepage or separate page -
3
index.php
The ultimate fallback for everything
Real World Example
If your site is set to show "Your latest posts" on the homepage:
- WordPress first looks for
front-page.php - If not found, it looks for
home.php - If neither exists, it uses
index.php
If set to show "A static page":
- Homepage uses:
front-page.phpβ custom page template βpage.phpβindex.php - Posts page uses:
home.phpβindex.php
Single Post Type Hierarchy
When displaying a single post, page, or custom post type, WordPress follows this hierarchy:
Interactive Template Selector
Click a content type to see its template hierarchy:
Select a content type above to see its template hierarchy...
Archive Page Hierarchy
Archive pages (categories, tags, dates, authors) have their own hierarchy:
-
1
category-{slug}.php
Specific category by slug (e.g., category-news.php) -
2
category-{id}.php
Specific category by ID (e.g., category-5.php) -
3
category.php
All category archives -
4
archive.php
All archive pages -
5
index.php
Ultimate fallback
<?php
// Example: Creating a specific category template
// File: category-tutorials.php
get_header(); ?>
<div class="tutorials-archive">
<header class="archive-header">
<h1 class="archive-title">
<?php single_cat_title( 'Tutorials: ' ); ?>
</h1>
<div class="archive-description">
<?php echo category_description(); ?>
</div>
</header>
<div class="tutorial-grid">
<?php
if ( have_posts() ) :
while ( have_posts() ) : the_post();
// Custom layout for tutorials
get_template_part( 'template-parts/content', 'tutorial' );
endwhile;
the_posts_pagination();
else :
get_template_part( 'template-parts/content', 'none' );
endif;
?>
</div>
</div>
<?php
get_sidebar( 'tutorials' );
get_footer();
Conditional Tags
WordPress provides conditional tags to check what type of page is being displayed. These are essential for controlling template logic:
Common Conditional Tags
Blog posts index page
Site front page (static or posts)
Any single post (of any post type)
Any single page
Category archive page
Any archive page
<?php
// Using conditional tags in templates
// Check multiple conditions
if ( is_front_page() && is_home() ) {
// Default homepage (showing latest posts)
} elseif ( is_front_page() ) {
// Static homepage
} elseif ( is_home() ) {
// Blog page (when not front page)
}
// Check for specific pages
if ( is_page( 'about' ) ) {
// Page with slug "about"
} elseif ( is_page( 42 ) ) {
// Page with ID 42
} elseif ( is_page( array( 'about', 'team', 'contact' ) ) ) {
// Any of these pages
}
// Check post types
if ( is_singular( 'product' ) ) {
// Single product post type
} elseif ( is_post_type_archive( 'product' ) ) {
// Product archive page
}
// Combine conditions
if ( is_single() && ! is_attachment() ) {
// Single post but not attachment
}
if ( is_archive() && ! is_category() && ! is_tag() ) {
// Archive but not category or tag
}
Custom Page Templates
You can create custom templates for specific pages that override the normal hierarchy:
<?php
/**
* Template Name: Full Width Layout
* Template Post Type: page, post
*
* @package My_Theme
*/
get_header(); ?>
<div class="full-width-container">
<?php
while ( have_posts() ) :
the_post();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class( 'full-width' ); ?>>
<header class="entry-header">
<?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
</header>
<div class="entry-content">
<?php
the_content();
wp_link_pages( array(
'before' => '<div class="page-links">' . __( 'Pages:', 'my-theme' ),
'after' => '</div>',
) );
?>
</div>
</article>
<?php
endwhile;
?>
</div>
<?php get_footer(); ?>
Debugging Template Loading
When templates aren't loading as expected, use these debugging techniques:
<?php
// Add to functions.php for debugging
// Show which template is being used
add_action( 'wp_head', 'show_template_file' );
function show_template_file() {
if ( current_user_can( 'manage_options' ) ) {
global $template;
echo '<!-- Template: ' . basename( $template ) . ' -->';
}
}
// Display all conditional tags
add_action( 'wp_footer', 'debug_conditional_tags' );
function debug_conditional_tags() {
if ( ! WP_DEBUG ) return;
?>
<div style="background: #f0f0f0; padding: 20px; margin: 20px;">
<h3>Active Conditional Tags:</h3>
<ul>
<li>is_home(): <?php var_dump( is_home() ); ?></li>
<li>is_front_page(): <?php var_dump( is_front_page() ); ?></li>
<li>is_single(): <?php var_dump( is_single() ); ?></li>
<li>is_page(): <?php var_dump( is_page() ); ?></li>
<li>is_archive(): <?php var_dump( is_archive() ); ?></li>
<li>is_category(): <?php var_dump( is_category() ); ?></li>
<li>is_tag(): <?php var_dump( is_tag() ); ?></li>
<li>is_author(): <?php var_dump( is_author() ); ?></li>
<li>is_search(): <?php var_dump( is_search() ); ?></li>
<li>is_404(): <?php var_dump( is_404() ); ?></li>
</ul>
</div>
<?php
}
// Use Query Monitor plugin for detailed template info
// Or use this simple function
function get_current_template() {
global $template;
return basename( $template );
}
Special Cases in the Hierarchy
404 Error Pages
WordPress uses this simple hierarchy:
404.phpindex.php
Search Results
Search results follow this path:
search.phpindex.php
Author Archives
Author pages check for:
author-{nicename}.php(e.g., author-john.php)author-{id}.php(e.g., author-3.php)author.phparchive.phpindex.php
Template Hierarchy Best Practices
- Start General: Build index.php first, then add specific templates as needed
- Use Meaningful Names: Name template files clearly (e.g., page-contact.php not page-2.php)
- Avoid Over-Specificity: Don't create too many specific templates - use conditional logic instead
- Document Templates: Add comments explaining what each template is for
- Test Thoroughly: Check that the right template loads for each type of content
- Use Template Parts: Keep templates DRY by using get_template_part()
- Consider Child Themes: Child themes inherit parent templates but can override them
Practice Exercise
Let's practice working with the template hierarchy:
Homework Preview
In this session's homework, you'll expand your minimal theme with multiple template files:
- Create header.php, footer.php, and sidebar.php
- Add single.php for blog posts
- Create page.php for static pages
- Build archive.php for archive pages
- Implement proper template hierarchy
- Use conditional tags appropriately
- Test with various content types