Child themes
A ready-made theme almost always needs tweaking: change the footer, add a block, alter the colours. If you edit the theme's own files, its very first update erases every change. The right way is a child theme: it takes everything from the parent and stores only the differences.
Creating
Create a folder next to the parent theme, for example wp-content/themes/mytheme-child, and in it a style.css file:
/*
Theme Name: My Theme Child
Template: mytheme
Version: 1.0.0
Text Domain: mytheme-child
*/
.site-footer {
background: #222;
color: #fff;
}The Template line is the folder name of the parent theme. It is the only thing that makes a theme a child. Activate it under "Appearance → Themes".
Adding the styles
// functions.php (the child theme)
add_action('wp_enqueue_scripts', function () {
wp_enqueue_style('mytheme-parent', get_template_directory_uri() . '/style.css');
wp_enqueue_style(
'mytheme-child',
get_stylesheet_uri(),
['mytheme-parent'],
wp_get_theme()->get('Version'),
);
});The child theme's styles load after the parent's and override them.
Overriding a template
To change a template, copy the file from the parent theme into the child with the same name and path — and edit the copy:
mytheme/footer.php → mytheme-child/footer.php
mytheme/template-parts/card.php → mytheme-child/template-parts/card.phpWordPress looks for a file in the child theme first and only then in the parent. That works for template parts too, provided the parent theme includes them with get_template_part().
functions.php is not replaced
Unlike templates, the child theme's functions.php does not replace the parent's but runs before it. So it holds only additions and changes — through hooks:
// functions.php (the child theme)
add_filter('excerpt_length', fn () => 30, 20);
add_action('after_setup_theme', function () {
remove_action('wp_footer', 'mytheme_print_credits');
}, 20);Priority 20 guarantees the code runs after the parent's code at priority 10.
Two addresses, two folders
| Function | What it returns |
|---|---|
get_template_directory() | The parent theme folder |
get_stylesheet_directory() | The active theme folder — the child |
get_template_directory_uri() | The parent theme address |
get_stylesheet_directory_uri() | The child theme address |
get_theme_file_uri('assets/logo.svg') | A file address: from the child theme, or from the parent if it is not there |
When a child theme is not needed
There is no reason to wrap your own theme in a child: nobody else's update will overwrite it. Nor is a child theme needed for a couple of CSS lines — they can go into "Appearance → Customize → Additional CSS". And features unrelated to design — post types, shortcodes — are written in a plugin.
Common mistake
If a function in the parent theme is declared without a function_exists() check, you cannot declare a function of the same name in the child — the result is a fatal "Cannot redeclare" error. Behaviour is changed not by redeclaring but by hooks: take the parent function off with remove_action() or remove_filter() and attach your own.