How to Create a WordPress Child Theme
A child theme is two files and a header comment. The part that goes wrong is not creating it — it is how the parent stylesheet gets loaded and what happens to your customiser settings on activation.
The whole thing is two files: a style.css with a Template: line naming the parent folder, and a functions.php that loads the parent stylesheet. Everything else is optional. If all you want is a few CSS rules, you do not need a child theme at all — additional CSS in the customiser survives updates perfectly well.
Use a child theme when you need to override template files, add PHP, or change theme behaviour in a way that must survive the next parent update.
Create the two files
Inside wp-content/themes/, make a folder. Name it after the parent with a -child suffix so it is obvious later:
wp-content/themes/
├── parent-theme/
└── parent-theme-child/
├── style.css
└── functions.php
style.css needs a header comment. Two lines matter: Theme Name and Template.
/*
Theme Name: Parent Theme Child
Theme URI: https://example.com/parent-theme-child
Description: Child theme of Parent Theme.
Author: Your Name
Template: parent-theme
Version: 1.0.0
Requires PHP: 8.0
License: GNU General Public License v2 or later
Text Domain: parent-theme-child
*/
Template must match the parent's folder name exactly — not its display name, not its title case. Twenty Twenty-Four is the name; twentytwentyfour is the folder. Get this wrong and WordPress refuses to activate the child with a "broken theme" notice.
Load the parent stylesheet the right way
Old tutorials tell you to put @import url("../parent-theme/style.css"); at the top of the child stylesheet. Do not. An @import blocks rendering until the imported file is fetched, and it fetches serially — the browser cannot even start the request until it has parsed the first stylesheet. Enqueue it instead:
<?php
add_action('wp_enqueue_scripts', function (): void {
wp_enqueue_style(
'parent-theme',
get_template_directory_uri().'/style.css',
[],
wp_get_theme(get_template())->get('Version'),
);
wp_enqueue_style(
'parent-theme-child',
get_stylesheet_uri(),
['parent-theme'],
wp_get_theme()->get('Version'),
);
});
Two details do the work here:
get_template_directory_uri()points at the parent;get_stylesheet_directory_uri()andget_stylesheet_uri()point at the child. Mixing them up is the single most common child-theme bug.- The dependency array
['parent-theme']guarantees the child stylesheet loads after the parent, so your rules win without!important.
Many modern parents already enqueue their stylesheet under a known handle. If so, reuse that handle as the dependency rather than loading style.css a second time — check the parent's functions.php for its wp_enqueue_style call before writing yours.
Override template files
To change a template, copy it from the parent into the child at the same relative path, then edit the copy:
parent-theme/template-parts/content-single.php
↓ copy to
parent-theme-child/template-parts/content-single.php
WordPress looks in the child first for every template it resolves, and falls back to the parent when the file is absent. Two exceptions are worth memorising:
functions.phpis not overridden. The child's file is loaded in addition to the parent's, and it loads first. That is why you hook rather than redeclare.- Parent functions are only replaceable if they are pluggable — wrapped in
if (! function_exists(...)). Otherwise redeclaring the name is a fatal error.
Copy only the files you actually change. A child theme that duplicates thirty parent templates has to be re-audited after every parent update, which defeats the purpose.
Child themes for block themes
The model is the same, the file names are not. A block child theme overrides templates/*.html and parts/*.html, and its theme.json is merged with the parent's rather than replacing it — so you declare only the settings and styles you want to change:
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"color": {
"palette": [
{ "slug": "brand", "color": "#1f3a5f", "name": "Brand" }
]
}
}
}
Be aware that Site Editor changes are stored in the database, not in your files, and they override both theme.json files. If a colour will not budge, the culprit is usually a saved global style — reset it from the Styles panel's revision list. The wider model is in what is a WordPress block theme.
Activate without losing your settings
Theme mods, widget placement and menu assignments are stored per theme. Activating a child theme starts that configuration empty, even though the parent is still doing the rendering. Before you switch:
- Take a backup.
- Screenshot every customiser panel and note which menus sit in which locations.
- Activate the child, then re-assign menus and widgets.
With WP-CLI you can copy the mods across instead of redoing them by hand:
wp option get theme_mods_parent-theme --format=json > mods.json
wp option set theme_mods_parent-theme-child "$(cat mods.json)" --format=json
Menus themselves are not deleted — only their location assignments are — so this is tedious rather than destructive. The rest of the switching checklist is in how to change a WordPress theme.
Common mistakes
Templatenaming the parent's display name instead of its folder. The theme will not activate.- Using
@importfor the parent stylesheet, which costs a render-blocking round trip. get_stylesheet_directory_uri()where the parent path was meant, producing a 404 for the parent stylesheet and an unstyled site.- Copying
functions.phpwholesale from the parent, which redeclares every function and fatals. - Editing the parent "just this once". The change is gone at the next update, and nobody remembers it was there.
- Building a child theme for a theme that ships its own hooks. Many commercial themes expect customisation through filters or a dedicated snippets area; check the documentation before duplicating templates.
Verify it works
Activate the child and confirm, in order: the site looks identical to before, style.css from both themes appears in the page source with the child last, one overridden template renders your change, and the front end has no missing-file 404s in the network panel. If something is off, debug mode will name the file and line faster than guessing.
Then update the parent theme deliberately, on a copy of the site, and check the same list again. Surviving an update is the entire reason the child theme exists — confirm it once rather than assuming it.
Frequently asked
- No. Additional CSS in the customiser or the Styles panel in a block theme survives parent updates and needs no extra files. A child theme earns its place when you override templates or add PHP.
- No. Theme mods, widgets and menu assignments are stored per theme, so activating a child theme presents an empty configuration. Screenshot your settings first, or copy the theme mods across before switching.
- Marginally, and only if the parent stylesheet is loaded twice. WordPress checks two directories for every template instead of one, which is negligible next to a single extra HTTP request.