iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Theme Anatomy

WordPress theme anatomy: required files, the template hierarchy, functions.php, the loop, and where to put each kind of code.

WordPress — theme anatomy

EXAMPLE
<?php
// ===== Minimum theme structure =====
// my-theme/
//   style.css          (REQUIRED — header doc block declares the theme)
//   index.php          (REQUIRED — fallback template)
//   functions.php      (optional — theme bootstrap + hooks)
//   screenshot.png     (optional — admin theme picker)
//   ... other templates as needed

// ===== style.css header =====
/*
Theme Name: My Theme
Theme URI: https://example.com/my-theme
Author: You
Description: A small custom theme.
Version: 1.0.0
License: GPL-2.0-or-later
Text Domain: my-theme
*/

// ===== Template hierarchy (most common routes) =====
// front-page.php       homepage when set in Settings -> Reading
// home.php             blog posts index
// single.php           single post
// page.php             single page
// archive.php          archives (category/tag/author/date)
// search.php           search results
// 404.php              not found
// header.php / footer.php / sidebar.php (partials)
// index.php            ultimate fallback

// More specific names win (e.g. category-news.php beats archive.php for the 'news' category).

// ===== functions.php =====
add_action('after_setup_theme', function () {
    add_theme_support('title-tag');
    add_theme_support('post-thumbnails');
    add_theme_support('html5', ['search-form', 'comment-form', 'comment-list', 'gallery', 'caption']);
    register_nav_menus([
        'primary' => __('Primary', 'my-theme'),
    ]);
});

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_style('my-theme', get_stylesheet_uri(), [], '1.0.0');
});

// ===== A page template using The Loop =====
// page.php
<?php get_header(); ?>
<main>
  <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
    <article id="post-<?php the_ID(); ?>">
      <h1><?php the_title(); ?></h1>
      <div><?php the_content(); ?></div>
    </article>
  <?php endwhile; endif; ?>
</main>
<?php get_footer(); ?>

// ===== header.php =====
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
  <meta charset="<?php bloginfo('charset'); ?>">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<header>
  <a href="<?php echo esc_url(home_url('/')); ?>"><?php bloginfo('name'); ?></a>
  <?php wp_nav_menu(['theme_location' => 'primary']); ?>
</header>

// ===== footer.php =====
<footer>(C) <?php echo date('Y'); ?> <?php bloginfo('name'); ?></footer>
<?php wp_footer(); ?>
</body></html>

// ===== Block themes (WordPress 6.x+) =====
// Block themes replace PHP templates with HTML files in /templates/ and /parts/,
// configured via theme.json. The hierarchy still applies; just .html instead of .php.

// ===== Patterns to internalise =====
// - Use wp_enqueue_style / wp_enqueue_script; never hard-code <link rel> tags
// - Escape output: esc_html, esc_attr, esc_url, wp_kses_post
// - Use a child theme when customising a parent
// - Block themes (theme.json) for new sites in 2026

// ===== Pitfalls =====
// - Editing parent theme files directly (lost on update)
// - Forgetting wp_head() / wp_footer() -> plugins/CSS break
// - Direct DB queries in templates -> slow; use WP_Query
// - Hard-coding URLs; use home_url(), site_url(), get_template_directory_uri()

Why it matters

A theme is style.css + index.php at minimum, with templates layered by hierarchy and behaviour added via functions.php. Enqueue assets correctly, escape output, use The Loop, and prefer child themes for customisation. Block themes are the modern path; classic themes are still everywhere.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
/*
    style.css       — theme metadata + global CSS
    functions.php   — boot code, hooks, enqueue
    index.php       — fallback template
    header.php / footer.php
    page.php / single.php / archive.php
*/
Try it Yourself »

Discussion

Loading…