Why child themes exist
Suppose you like Twenty Twenty-Five but want a different colour scheme and your own footer. Editing its files is a bad idea: the next theme update replaces them and your work vanishes. A child theme solves this. It inherits everything from a parent theme and overrides only what you change. The parent can then be updated as normal.
For design changes alone, the Site Editor is often enough. A child theme is the right choice when you want your changes in files: under version control, deployed with your code, and reusable across sites.
The minimum: style.css
A child theme is a folder with a style.css whose header names the parent with Template: (the parent's folder name):
/*
Theme Name: Twenty Twenty-Five Bakery
Template: twentytwentyfive
Description: Bakery customisations for Twenty Twenty-Five.
Version: 1.0.0
Text Domain: bakery-child
*/That is already a working child theme. Activate it:
wp theme activate bakery-child
wp eval 'echo "template: ", get_template(), "\nstylesheet: ", get_stylesheet(), "\n";'Success: Switched to 'Twenty Twenty-Five Bakery' theme.
template: twentytwentyfive
stylesheet: bakery-childget_template() (and the template option) is the parent; get_stylesheet() is the active child. The site looks exactly like Twenty Twenty-Five, because nothing is overridden yet.
Overriding styles with theme.json
The child's theme.json is merged over the parent's, so it only needs the values you change. Twenty Twenty-Five names its main colours base, contrast and accent-1 to accent-6. Changing two of them recolours the whole site:
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"color": {
"palette": [
{ "slug": "base", "name": "Flour", "color": "#fbf7f0" },
{ "slug": "contrast", "name": "Cocoa", "color": "#2b1d14" },
{ "slug": "accent-1", "name": "Crust", "color": "#8a4b20" }
]
}
}
}<?php
foreach ( wp_get_global_settings( [ 'color', 'palette', 'theme' ] ) as $colour ) {
echo str_pad( $colour['slug'], 10 ), $colour['color'], " ", $colour['name'], "\n";
}base #fbf7f0 Flour
contrast #2b1d14 Cocoa
accent-1 #8a4b20 CrustNote one subtlety: arrays such as the palette are replaced, not merged item by item. Our child listed three colours, so the parent's other accent colours are gone from the palette. To keep them, copy them into the child's palette too.
Overriding templates and parts
Any template or template part with the same name in the child replaces the parent's. A new footer:
<!-- wp:group {"tagName":"footer","layout":{"type":"constrained"}} -->
<footer class="wp-block-group">
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">Fresh bread daily · 12 Market Street</p>
<!-- /wp:paragraph -->
</footer>
<!-- /wp:group --><?php
foreach ( [ 'parts/header.html', 'parts/footer.html', 'templates/single.html' ] as $file ) {
echo str_pad( $file, 22 ), str_replace( get_theme_root() . '/', '', get_theme_file_path( $file ) ), "\n";
}parts/header.html twentytwentyfive/parts/header.html
parts/footer.html bakery-child/parts/footer.html
templates/single.html twentytwentyfive/templates/single.htmlGET /Fresh bread daily · 12 Market Streetget_theme_file_path() looks in the child theme first and falls back to the parent. The footer comes from the child; the header and the single post template still come from the parent, because the child does not have them. The same rule applies to templates/*.html and patterns/*.php.
functions.php in a child theme
A child theme can have its own functions.php. Unlike templates, it does not replace the parent's: WordPress loads the child's first, then the parent's. Use it to add features or to unhook something the parent does.
When referring to files, use the right function:
| Function | Points to |
|---|---|
get_template_directory(), get_template_directory_uri() |
the parent theme |
get_stylesheet_directory(), get_stylesheet_directory_uri() |
the child (the active theme) |
get_theme_file_path( 'file' ), get_theme_file_uri( 'file' ) |
the child's copy if it exists, otherwise the parent's |
get_theme_file_uri() is usually the best choice, because it lets a child override any asset simply by providing a file with the same name.
Classic child themes
Child themes of classic themes work the same way, with PHP template files (header.php, single.php) instead of HTML templates. In older tutorials you will see @import of the parent stylesheet in style.css; that is outdated. Enqueue styles from functions.php instead, as the next lesson shows.
Common mistakes
- Wrong
Template:value: it must be the parent's folder name, not its display name; otherwise the theme shows as broken. - Copying the whole parent into the child, which defeats the purpose; copy only the files you change.
- Expecting the palette to merge colour by colour.
- Using
get_template_directory_uri()for files that live in the child.
Exercise
Override Twenty Twenty-Five's single template in your child theme so that single posts show a line "Thanks for reading!" after the content. Where do you get a starting copy of the template?
Show one possible answer
Copy wp-content/themes/twentytwentyfive/templates/single.html to wp-content/themes/bakery-child/templates/single.html, then add after the Post Content block:
<!-- wp:paragraph --><p>Thanks for reading!</p><!-- /wp:paragraph -->Alternatively, edit the template in the Site Editor and use Export to get the customised file. Single posts now use the child's template; everything else still comes from the parent.
Key points
- A child theme inherits everything from a parent theme and overrides only what you change, so parent updates keep working.
- It needs a style.css with a Template: line naming the parent's folder.
- The child's theme.json is merged over the parent's; a template or part with the same name in the child replaces the parent's.
- get_template() returns the parent, get_stylesheet() the child; use get_stylesheet_directory() for the child's files.