WordPress Development

WordPress Child Themes: When You Need One and When You Don’t

A child theme is the right answer to one problem: overriding template files in a theme that still receives updates. For CSS tweaks and a few PHP snippets, it is overhead you maintain forever for no benefit.

WordPress Child Themes: When You Need One and When You Don’t

Open the child theme folder on a typical WordPress site and you find two files. A style.css with a header comment and maybe thirty lines of CSS, and a functions.php holding one enqueue snippet copied from a tutorial. No overridden templates. Nothing else.

That child theme is not protecting anything. It exists because most guides on customising WordPress open with “first, create a child theme,” and the instruction gets followed before anyone asks what it is meant to protect. It adds a second stylesheet request to every page load and a second theme to keep track of.

Child themes are the right tool for one job and they are very good at it. The advice to build a WordPress child theme before you touch anything has outrun that job by a wide margin, and the cost of an unnecessary one is not zero. It gets paid slowly, every time the parent theme updates.

Diagram contrasting a child theme's functions.php, which loads in addition to the parent's, with a template file, which replaces the parent's copy entirely

What a child theme actually is

Mechanically it is almost nothing. A child theme is a directory in wp-content/themes/ containing a style.css whose header comment names a parent theme. That is the entire requirement. Everything else, including functions.php, template files, screenshot.png and theme.json, is optional.

Two fields in that header carry the weight: Theme Name and Template. The Template value is the parent theme’s folder name, not its display name, and it has to match exactly. Twenty Twenty-Four lives in a folder called twentytwentyfour, so that is what goes in the header.

/*
Theme Name:  Twenty Twenty-Four Child
Template:    twentytwentyfour
Version:     1.0.0
Text Domain: twentytwentyfour-child
*/

Save that as style.css inside wp-content/themes/twentytwentyfour-child/ and the child theme appears under Appearance > Themes, ready to activate. Get the Template line wrong and WordPress flags the theme as broken with the message “Template is missing,” telling you to install the parent theme it cannot find.

Once the child is active, two path helpers stop meaning the same thing. get_stylesheet_directory() points at the child. get_template_directory() points at the parent. Most “why isn’t my override loading” questions trace back to one of those two being used where the other was needed.

Additive functions, replacing templates

Here is the part most tutorials skip, and it is the source of most of the confusion around child themes.

functions.php is additive. WordPress includes the child’s functions.php first and the parent’s immediately after. Both run. You are not replacing the parent’s functions file, you are running ahead of it.

Template files are replacing. Put single.php in the child and WordPress uses it instead of the parent’s single.php. The parent’s version is never loaded, never merged, never consulted. The same goes for header.php, footer.php, archive.php and any partial the parent pulls in with get_template_part().

That load order has a practical consequence. Because the child runs first, you cannot simply redeclare a function the parent defines. PHP throws a fatal “cannot redeclare” error when the parent file loads afterwards. Well-built parent themes wrap their overridable functions in if ( ! function_exists( 'theme_function_name' ) ) precisely so a child can define its own version first. If the parent did not do that, the function is not overridable and you need a filter or an action removal instead.

The replacing behaviour has a limit too. Overrides only work where the parent goes through the standard lookup, meaning locate_template(), get_template_part(), get_header() and the template hierarchy itself, all of which check the child directory before the parent. If the parent theme does something like include get_template_directory() . '/inc/helpers.php', that path is pinned to the parent and no file in your child theme will ever be picked up in its place.

Loading the parent stylesheet correctly

Old tutorials tell you to put @import url("../parenttheme/style.css"); at the top of the child’s style.css. Don’t. The browser has to download and parse the child stylesheet before it discovers the import, then start a second request, so the two files load in series instead of in parallel and rendering is blocked for the length of both. The theme handbook has advised against it for years.

Enqueue the parent stylesheet from the child’s functions.php instead, and declare the child stylesheet as depending on it so the order is guaranteed.

<?php
add_action( 'wp_enqueue_scripts', 'childtheme_enqueue_styles' );

function childtheme_enqueue_styles() {
    $parent = wp_get_theme( get_template() );

    wp_enqueue_style(
        'parent-style',
        get_parent_theme_file_uri( 'style.css' ),
        array(),
        $parent->get( 'Version' )
    );

    wp_enqueue_style(
        'child-style',
        get_stylesheet_uri(),
        array( 'parent-style' ),
        wp_get_theme()->get( 'Version' )
    );
}

get_parent_theme_file_uri() always resolves to the parent directory, which is what you want here, and get_stylesheet_uri() always resolves to the active theme’s style.css, which is the child’s. Passing each theme’s own version string as the fourth argument means the cache-busting query string changes when you bump the version instead of never changing at all.

One caveat before you paste that in. Plenty of parent themes already enqueue their stylesheet with get_stylesheet_uri(), which under a child theme resolves to the child’s file. In that case the snippet above loads the same file twice under two handles, because WordPress deduplicates by handle, not by URL. Look at what the parent registers first. If it already has a handle for its stylesheet, drop the first wp_enqueue_style() call and list that existing handle as your dependency.

The one case that genuinely needs a child theme

You are overriding template files in a theme that somebody else maintains and that receives updates.

That is the whole case. If the single-post template has to output an author box in a position no hook exposes, you copy single.php, or whatever partial the theme uses, into the child and edit your copy. When the parent updates, your copy survives. Edit the parent directly and the update overwrites the file with no undo.

When you copy a template into a child theme, mirror the parent’s directory structure exactly. A theme that calls get_template_part( 'template-parts/content', 'single' ) looks for template-parts/content-single.php, and it checks the child directory for that path before falling back to the parent:

my-theme-child/
    style.css
    functions.php
    template-parts/
        content-single.php

Drop that same file in the child theme’s root and nothing happens. The lookup is path-sensitive and there is no error when it fails to match. You keep seeing the parent’s output and wonder why.

If you have decided you need one, there is no reason to write the boilerplate by hand. Fill in the parent directory below and the generator builds the theme.

It writes the style.css header in the order WordPress reads it, the functions.php with the enqueue that matches your case, block theme or classic, and a screenshot, then hands the whole folder over as a zip. No account, no upload, no generator service in between.

Child theme generator

Name the parent theme folder and get a child theme back that works as it is: style.css with the header in the order WordPress reads it, functions.php with the right enqueue, and a screenshot drawn here. The ZIP is built in this browser tab, nothing is uploaded and no generator service is involved.

The folder name under wp-content/themes, not the name shown under Appearance. Lower case, a to z, 0 to 9 and hyphens. It has to match the folder exactly, folder names are case sensitive on most servers.

Derived from the theme name until you edit it yourself.

How the stylesheet is loaded

Also include

A template or part in the child replaces the parent version of it completely. The two stubs are there to start from, delete whichever you do not intend to change.


Then what
  1. Upload the ZIP under Appearance, Themes, Add New, Upload Theme. Over SFTP, copy the unzipped folder into wp-content/themes/ instead.
  2. Activate the child theme, and leave the parent installed and updated. A child theme cannot run without its parent.
  3. Redo the settings by hand. Customizer options, widgets and menu locations are stored per theme, so they do not follow the switch. Write down what you have set before you activate.
WunderPaint
The Dynamic Design and Automation Studio
WunderPaint is a layered image editor for your WordPress media library. WunderPaint Studio is the same thing in any browser, free and without an account.

Where PHP snippets belong

If your entire customisation is a handful of add_filter() and add_action() calls, a child theme is the wrong container. A small site-specific plugin is better in three ways, and the differences are not academic.

It survives a theme switch. A child theme’s functions.php stops running the moment you activate a different theme, and everything in it goes quiet at once. Shortcodes stop resolving, custom post types vanish from the admin, registered image sizes stop being generated. A plugin keeps running.

It can be switched off. If a snippet in a plugin causes a fatal error, you deactivate the plugin or rename its folder over SFTP. A fatal error in the active theme’s functions.php takes the whole front end down along with the admin, and you are into recovery-mode emails and file manager surgery to get back in.

And it separates concerns honestly. A theme file is for presentation, while behaviour that should outlive your current design belongs elsewhere. That boundary, what belongs in functions.php and what belongs in a plugin, decides more about a site’s long-term maintainability than the choice of theme does.

A site-specific plugin is one file with a header comment, dropped into wp-content/plugins/:

<?php
/**
 * Plugin Name: Example Site Tweaks
 * Description: Small customisations specific to this site.
 * Version:     1.0.0
 */

add_action( 'after_setup_theme', function () {
    add_image_size( 'card-thumb', 600, 400, true );
} );

That example is deliberate. Registering a custom image size is one of the most common reasons people are told to build a child theme, and it is one of the worst fits for one. The size only applies to images uploaded after it is registered, so if it stops being registered because you changed themes, every file it already generated stays on disk while nothing on the site asks for it any more. Put it in a plugin and it keeps working through a redesign.

Where CSS belongs

If your customisation is only CSS, you need no child theme at all. Additional CSS in the Customizer stores your rules in the database and WordPress prints them late in the <head>, after the enqueued stylesheets, so rules of equal specificity win on source order. It survives parent theme updates for the same reason a child theme does: it is not in the theme’s files. Block themes have the same field under Styles in the Site Editor, and plenty of commercial themes ship their own equivalent in their options panel.

The one real limitation is that Additional CSS is stored per theme, so it does not follow you when you switch. Neither does a child theme’s style.css. On that axis they are equivalent, and the box that needs no files, no FTP and no enqueue snippet wins.

The cost of a frozen copy

An overridden template file is a frozen copy. That sounds like the point, because it is why you made it, but consider what freezing means over time.

Say the parent theme ships an update that fixes an escaping bug in content-single.php, changes the markup so a new block style applies, and adds a do_action() hook that three of the theme’s own add-ons rely on. Your copy of that file receives none of it. Nothing in the admin tells you. The Themes screen shows the parent as up to date, because it is. You are simply no longer using the file that was updated.

Override five templates and you have five files to diff against the parent every time the parent ships a major release. Very few tools help. WooCommerce is the notable exception: its template files carry a version number in the file header, and its System Status report lists overridden templates that have fallen behind the version the plugin expects. Core and almost every theme offer nothing equivalent. You are the version check.

This is the argument for overriding as little as possible. Before copying a template, look for a hook, a filter or a theme setting that gets you the same result. A three-line filter in a plugin costs nothing at update time. A copied 200-line template costs a review, forever.

Timeline showing an overridden child theme template silently missing an accessibility fix, a new hook and a markup change across successive parent theme releases

Block themes change the arithmetic

With a block theme, editing a template in the Site Editor does not touch a file. WordPress saves your version as a wp_template post in the database, and from then on the database copy takes priority over the theme’s own templates/*.html file. You get template customisation that survives updates without creating a child theme at all.

The trap moved rather than disappeared. That database copy freezes in exactly the same way a child theme override does, because updates to the underlying file stop reaching your site. The difference is that the Site Editor gives you a way out: a customised template offers an action that discards the database copy and returns you to the theme’s current file. There is no equivalent button for a copied PHP template.

Child themes still have a place with block themes, mostly when you want customisations in files you can version-control and deploy rather than in a database you have to migrate. There is also one genuinely useful piece of asymmetry: a child theme’s theme.json is merged into the parent’s rather than replacing it, with the child’s values taking precedence, so you can override a few palette colours or spacing values without restating the parent’s entire configuration. That is closer to how functions.php behaves than to how templates behave.

Which option fits

  • CSS only, no PHP: Additional CSS in the Customizer, or the theme’s own custom CSS field. No child theme.
  • A handful of PHP snippets: a site-specific plugin. It survives theme switches and can be deactivated when it breaks.
  • Template overrides on a theme that receives updates: a child theme. This is what child themes are for.
  • A block theme where you only need layout changes: edit in the Site Editor, and remember the result lives in the database.
  • A theme you built yourself that nobody else updates: no child theme. Edit the theme. There is no upstream to protect against.

Most real sites are a mix, and the answer there is both: a child theme for the templates, a plugin for the snippets. Splitting them is not overkill, it is what makes the next redesign survivable.

When something looks wrong

The child theme activates but the site is completely unstyled. The parent stylesheet is not being loaded. Either the child’s functions.php has no enqueue for it, or the enqueue used get_stylesheet_directory_uri(), which points at the child, where it needed the parent’s URI.

WordPress says the parent theme is missing. The Template line in the child’s style.css does not match the parent’s folder name. It is the directory name, not the display name, and on most servers it is case-sensitive.

A fatal “cannot redeclare function” error after editing functions.php. The child’s functions.php loads before the parent’s, so a function you defined collides when the parent file declares the same name. Either the parent wraps that function in function_exists() and you spelled the name wrong, or it does not and the function was never meant to be overridden.

The copied template file has no effect. The path in the child does not mirror the path in the parent, or the parent loads that file with a hardcoded get_template_directory() include rather than through the standard lookup. Only files reached through the template hierarchy or functions like locate_template() can be overridden.

Decision table showing that only template overrides on an updating parent theme genuinely need a child theme, while CSS, PHP snippets and block themes have lighter homes

Customisations disappeared after a theme update. The edits were made directly in the parent theme’s files, not in a child. There is no recovery except a backup, which is the actual reason child themes exist and the only symptom on this list they prevent.

Where this leaves you

A child theme is not a safety measure you apply to a site in general. It is a targeted answer to one question: how do I change a file that somebody else is going to overwrite? If nobody is going to overwrite the file, or if you are not changing a file at all, the question does not apply and the child theme is structure without purpose.

The most useful reframing is to stop thinking of it as protection and start thinking of it as a fork. Every template you copy into a child theme is a small fork of somebody else’s code, and forks have upkeep. That is a reasonable trade for a change you genuinely need and cannot get from a hook. It is a bad trade for a change you could have made with six lines of CSS.

If you already have a near-empty child theme, you do not have to tear it down. It is not hurting much beyond an extra request. But when the next customisation comes up, ask what it actually is before deciding where it goes. CSS to the CSS box, snippets to a plugin, templates to the child theme. Sorted that way, each piece ends up somewhere it can survive the thing most likely to break it.

WordPress Child Themes: When You Need One and When You Don’t

Table of Contents

Learn it by building something

Every week one thing you can make the same afternoon, from dynamic templates to 3D type. Written down step by step.

One mail a week, and then it ends.
Unsubscribe in one click.

Design Fundamentals

How to Choose a Color Palette Without Learning Color Theory

Palette generators hand you five swatches of equal weight, which is the one thing a real palette never is. Here is the ten minute version that works.

WordPress Development

One Design, Two Hundred Names: Designing From a Spreadsheet

Somebody needs two hundred name badges by Thursday. The spreadsheet with all those names already exists, and typing them a second time is pure waste.

SEO & Structured Data

WordPress Image SEO: What Works and What Is Folklore

Most image SEO checklists are ordered by how easy each item is to write about. This one ranks the advice by mechanism instead, naming the core function behind every claim, and says plainly which parts are folklore.

Photo Editing

Make a tidy application photo out of an ordinary phone snapshot

A face detector of 190 KB returns a grid of anchors, a box and five landmark points, and everything after that is arithmetic: head height, eye line, the angle to level by, millimetres to pixels. An application photo, explicitly not an official passport photo, made without uploading your face anywhere.

SEO & Structured Data

WordPress Alt Text: Where It Lives and Why Your Edits Do Not Show

Alt text in WordPress is one postmeta row, copied into the post markup the moment you insert an image. That single fact explains why editing the library changes nothing on pages you already published, why an audit has two halves, and what to fix first.

Developer Tools

Dummy Text Generator: Lorem Ipsum That Behaves Like Real Copy

Lorem ipsum has a longest word of thirteen letters and no umlauts at all, so a layout tested with it is tested with the easiest text it will ever hold. What placeholder text should actually prove, and a generator that produces it.

Download the free WunderPaint Plugin for WordPress

The WunderPaint workspace with the layers panel, adjustment sliders, text style presets and the asset library along the bottom

The Image Editor & Design Studio

Everything described here can be done in the browser, on your own site. The live demo runs the full editor with nothing to install.

Free

Chaos Art

Autonomous painters make one-of-a-kind abstract art in 3D space - gestures, art movements, painterly media, and embeds that paint a new original for every visitor.

Pro

Particle Strokes

Paint with swarms of light: twenty-two movements, a stamp you draw yourself, and curves that give a stroke a shape - the swarm keeps painting for a few seconds after you let go.

Pro

City Diorama

Any place on earth as a miniature you could hold: real streets, water and building footprints raised into a 3D diorama - or wrapped around a sphere as your own tiny planet.

Free

Papercut Art

Layered paper pictures with real depth - a photo sliced along its actual depth into up to twenty layers, parametric landscapes, animals and clouds you can shape, letters with real counters, and a look that runs on three dials.

Pro

3D Earth Studio

A hyperrealistic globe - day and night with city lights, live clouds, atmosphere halo, country borders and highlights, click-to-place markers with flight-route arcs, satellite orbits, seamless rotation video and a live website embed.

Free

Mystic Studio

Turn a birth date into wall art - a real natal chart with houses and aspects, the moon of that night, zodiac and Chinese zodiac posters, numerology cards and a synastry wheel for two, in eight artful themes.

Free

Marble Bath

Marble paper on a virtual water bath - drop, rake and comb real Ebru patterns with gestures, flowers and classic recipes, razor-sharp at any size and re-editable as a layer.

Free

Day Ring

Turn a day into a beautiful circular schedule - colour-coded time blocks as arcs around a 24-hour clock, with concentric rings for overlaps, emoji, templates and a legend.

Free

Code Shot

Turn code into a gorgeous, share-ready image - syntax highlighting, editor themes, window frames and diff highlighting - then drop it into your design as a re-editable layer.

Pro

3D Solar System Studio

Build a date-accurate 3D solar system - real planet positions for any date, photoreal textures and one slider from artistic to true scale - then drop it into your design as an editable layer.

Pro

3D Molecule Studio

Build a real 3D molecule - from a curated library, the periodic table or a SMILES string - then style it, measure it and drop it into your design as an editable layer.

Pro

3D Textile Studio

Drop your design onto cloth that behaves like the material you pick: silk falls soft, felt holds its shape, flag fabric snaps in the wind. Hang it, blow it and drape it, then lay the finished drape back into your document as a picture.

Pro

3D Particle Studio

Point the engine at any layer and it becomes a cloud of particles that keeps its colours, flowing through a sphere, a galaxy or your own outline. Keep the frame you like as a still, or embed the running engine so it keeps moving on your page.

Free

Origami

Put your own picture on the paper and watch that very sheet fold itself into a crane or a box. Every step is a station you can stop at and turn around in 3D, which is exactly where printed diagrams leave you alone.