A child theme exists so parent theme updates do not overwrite your changes. With block themes and the Site Editor, a growing share of customisation no longer needs one at all.
The advice “always use a child theme” is a decade old and was correct for classic themes, where any customisation meant editing PHP templates. Block themes changed that: the Site Editor stores its changes in the database, and updating the parent leaves them alone.
So the question is now genuinely worth asking, and the answer depends on what you are changing.
Table of contents
- The minimum setup
- How overriding works
- When you no longer need one
- Practices that keep it maintainable
- Testing an update before it reaches visitors
- How this fits the rest of the stack
- FAQ
The minimum setup
Two files in wp-content/themes/parent-child/.
/* style.css */
/*
Theme Name: Parent Child
Template: parent-theme-folder-name
Version: 1.0.0
*/
Template is the critical field: it must be the parent’s directory name, exactly, including case. Not its display name. Getting it wrong gives you a broken theme with an unhelpful error.
<?php
// functions.php
defined( 'ABSPATH' ) || exit;
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style(
'parent-child',
get_stylesheet_directory_uri() . '/style.css',
array( 'parent-style-handle' ),
wp_get_theme()->get( 'Version' )
);
} );
Two details in that enqueue that most tutorials get wrong.
The dependency array must contain the parent’s actual style handle, which you find by reading the parent’s functions.php. Guessing is why child styles sometimes load before parent styles and appear to be ignored.
And do not use @import in style.css to pull in the parent stylesheet. It blocks rendering while the browser discovers and fetches a second file serially. That advice is long obsolete and still widely copied.
For block themes, add theme.json to the child. It is merged with the parent’s rather than replacing it, so you only declare what differs.
How overriding works
WordPress checks the child theme directory first for any template file, then falls back to the parent. So copying single.php into the child and editing it overrides the parent’s version, and the parent’s stays untouched through updates.
The rules by file type:
- Template files (
single.php,page.php,archive.php) — copied to the child and edited. Child wins. functions.php— not overridden. The child’s loads first, then the parent’s. Both run.style.css— not automatically loaded for the parent; you enqueue both, as above.- Block templates in
templates/andparts/— child wins, same as classic templates. theme.json— merged, with child values taking precedence.
The functions.php behaviour catches everyone once. You cannot replace a parent function by redefining it — that is a fatal redeclaration error. Instead, if the parent wrapped it correctly in function_exists(), defining yours first wins because the child loads first. If it did not, remove its hook and add your own:
add_action( 'after_setup_theme', function () {
remove_action( 'wp_footer', 'parent_theme_footer_credit' );
add_action( 'wp_footer', 'my_footer_credit' );
}, 11 ); // priority 11 -- after the parent has registered it
The priority matters: you cannot remove a hook that has not been added yet.
When you no longer need one
With a block theme, these are stored in the database and survive parent updates with no child theme involved:
- Template edits in the Site Editor.
- Template part changes — header, footer.
- Global styles: colours, typography, spacing.
- Custom block patterns created in the editor.
- Navigation menus.
That covers a large share of what people used to build child themes for. If your customisation is entirely in that list, a child theme adds a directory and a maintenance obligation for nothing.
You still need one for:
- PHP — custom functions, hooks, filters.
- Template files the Site Editor cannot express.
- Registering post types, taxonomies or blocks from the theme.
- CSS you would rather version in files than paste into Additional CSS.
- Any classic theme, where template edits mean editing PHP.
Worth noting that custom post types and similar functionality arguably belong in a small site-specific plugin rather than a theme at all, so they survive a theme change. A child theme is for presentation; a plugin is for behaviour, and mixing them is why switching themes sometimes deletes half a site’s functionality.
Practices that keep it maintainable
- Prefix everything. Function names, handles, option keys.
mytheme_in front of everything avoids collisions with the parent and with plugins. - Do not copy the entire parent theme in. Copy only the files you actually change. Every copied file is one that stops receiving the parent’s fixes.
- Version your enqueues with
wp_get_theme()->get( 'Version' )rather than a hardcoded string, so bumping the version busts the cache. - Keep
functions.phpshort. Break substantial code into files underinc/and require them. - Track it in Git. A child theme is source code.
- Re-check after parent updates. If the parent restructures a template you copied, your override may silently drop new markup.
That last one is the ongoing cost of a child theme, and the reason to copy as few files as possible. An overridden template is frozen at the moment you copied it.
Testing an update before it reaches visitors
The scenario a child theme protects against is a parent update overwriting your work. The related risk it does not protect against is a parent update changing markup or hooks your child theme depends on.
The right habit is testing theme and plugin updates somewhere that is not the live site, and having a way back if something goes wrong anyway.
Managed WordPress on RunxBuild includes a file manager in the dashboard — browse, edit, upload, unzip and download — and a database browser for tables and SQL, so setting up a child theme or inspecting what an update changed is a browser task rather than an SFTP-and-phpMyAdmin one. Plans start at $3/month, which makes keeping a separate copy for testing updates a reasonable thing to do.
How this fits the rest of the stack
Two files set up a child theme, and the details that matter are the exact Template directory name, enqueuing against the parent’s real style handle, and never using @import. With a block theme, check first whether the Site Editor already covers what you are changing — often it does, and the child theme is maintenance you did not need. The RunxBuild hosting calculator shows managed WordPress plans, including keeping a second copy for testing updates.
Useful related references:
- The Fastest WordPress Theme Is Rarely Your Actual Problem
- WordPress Featured Image Size: 1200x630 and Why Your Theme Crops It
- Is WordPress Multisite One Theme or Multiple? How Themes Actually Work Across a Network
- Services on RunxBuild
FAQ
Do I still need a child theme with block themes?
Only for PHP, template files the Site Editor cannot express, or file-based CSS. Site Editor template edits, global styles, template parts and patterns are stored in the database and survive parent updates without one.
What files does a child theme need?
style.css with a Theme Name and a Template field naming the parent’s directory exactly, plus functions.php enqueuing the child stylesheet. For block themes, add theme.json, which is merged with the parent’s rather than replacing it.
Does a child theme functions.php replace the parent’s?
No. Unlike template files, both load — the child’s first, then the parent’s. You cannot redefine a parent function without a fatal error, so remove its hook and add your own instead, at a priority late enough that the parent has registered it.
Should I use @import to load the parent stylesheet?
No. It blocks rendering while the browser serially discovers and fetches the second file. Enqueue both stylesheets in functions.php, with the child declaring the parent’s actual style handle as a dependency.
Why is my child theme not working?
Most often the Template field does not exactly match the parent’s directory name, including case. Second most often, the child stylesheet is enqueued without the parent’s real handle as a dependency, so it loads in the wrong order.