SponsoredHosinger Special Offer

WP WordPress Theme Development

Build classic and block WordPress themes from scratch: the template hierarchy, The Loop, the_title() and the_content(), template parts, menus, the Customizer, child themes and theme.json.

The Template Hierarchy

WordPress Theme Development Lesson 5 of 30 ~4 min read

Overview

The template hierarchy is the fixed order in which WordPress looks for a template file for each request — it tries the most specific file first and falls back step by step until it reaches index.php.

Understanding it is what separates guessing from theme development. Once you know the order, you can change how one category, one page or one post type looks just by creating a file with the right name — no if statements needed.

How the lookup works

For a single blog post with the slug hello-world, WordPress checks for these files in this order and uses the first one that exists:

  1. single-post-hello-world.php — this exact post
  2. single-post.php — any post of type post
  3. single.php — any single post of any type
  4. singular.php — any single post or page
  5. index.php — the final fallback, always present

If your theme has only index.php, everything uses it. Add single.php and posts suddenly get their own layout, while pages and archives are unaffected.

The hierarchy for common page types

Visitor is viewingWordPress tries, in order
The front pagefront-page.php → home.php or the page hierarchy → index.php
The blog posts indexhome.php → index.php
A single postsingle-{post-type}-{slug}.php → single-{post-type}.php → single.php → singular.php → index.php
A pageAssigned page template → page-{slug}.php → page-{id}.php → page.php → singular.php → index.php
A categorycategory-{slug}.php → category-{id}.php → category.php → archive.php → index.php
A tagtag-{slug}.php → tag-{id}.php → tag.php → archive.php → index.php
An authorauthor-{nicename}.php → author-{id}.php → author.php → archive.php → index.php
A date archivedate.php → archive.php → index.php
A custom post type archivearchive-{post-type}.php → archive.php → index.php
A custom taxonomy termtaxonomy-{taxonomy}-{term}.php → taxonomy-{taxonomy}.php → taxonomy.php → archive.php → index.php
Search resultssearch.php → index.php
A missing page404.php → index.php

front-page.php versus home.php

This trips up almost everyone, because the names suggest the opposite of what they do.

  • front-page.php renders the site's home page — whatever is at your root URL — regardless of the Reading settings.
  • home.php renders the blog posts index. If Settings → Reading shows "Your latest posts", that index is the home page too. If it is set to a static page, the blog index moves to the "Posts page" you chose, and home.php renders that page instead.
Tip: A practical rule: use front-page.php for a marketing-style home page, and home.php for the list of blog posts.

Using the hierarchy on purpose

Say the "News" category (slug news) needs a different layout from every other category. You do not touch archive.php at all — you create a new file:

<?php
/**
 * category-news.php
 *
 * WordPress picks this file automatically for /category/news/,
 * because category-{slug}.php is checked before archive.php.
 */
get_header();
?>

<main class="news-archive">
    <h1 class="news-archive__title">Latest News</h1>

    <?php if ( have_posts() ) : ?>
        <?php while ( have_posts() ) : the_post(); ?>
            <?php get_template_part( 'template-parts/content', 'news' ); ?>
        <?php endwhile; ?>
    <?php endif; ?>
</main>

<?php
get_footer();

Every other category still uses archive.php. That is the hierarchy doing exactly what it is for.

Seeing which template was used

With Query Monitor active, open any page on the front end and click the admin bar entry. The Template panel shows the file that rendered the page and the full list of candidates WordPress tried. This is the fastest way to learn the hierarchy — browse your site and watch it.

Common mistakes

  • Naming a file category-News.php — slugs are lowercase, so it is never found.
  • Using an ID-based name like page-42.php on a site that will be migrated. IDs change between environments; slugs usually do not.
  • Putting if ( is_category( 'news' ) ) checks inside archive.php instead of creating category-news.php.

Practice

  • Copy index.php to single.php and change the heading. Open a post and a page — only the post changes.
  • Create page-about.php for a page with the slug about and confirm it is used only for that page.
Create a free account to save which lessons you've finished. Save my progress