Himanshu SharmaSoftware engineer
Let’s talk

WordPress · Lesson 22 of 45

Child themes

Customise an existing WordPress theme safely with a child theme, overriding theme.json settings, templates and parts while keeping the parent theme's updates.

12 minBlock themesUpdated 23 October 2026

By the end of this lessonCreate a child theme of a block theme, override its styles and templates, and explain how WordPress decides which theme's file to use.

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):

css
/*
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:

bash
wp theme activate bakery-child
wp eval 'echo "template: ", get_template(), "\nstylesheet: ", get_stylesheet(), "\n";'
result
Success: Switched to 'Twenty Twenty-Five Bakery' theme.
template: twentytwentyfive
stylesheet: bakery-child

get_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:

json
{
	"$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
<?php
foreach ( wp_get_global_settings( [ 'color', 'palette', 'theme' ] ) as $colour ) {
	echo str_pad( $colour['slug'], 10 ), $colour['color'], "  ", $colour['name'], "\n";
}
result
base      #fbf7f0  Flour
contrast  #2b1d14  Cocoa
accent-1  #8a4b20  Crust

Note 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:

html
<!-- 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
<?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";
}
result
parts/header.html     twentytwentyfive/parts/header.html
parts/footer.html     bakery-child/parts/footer.html
templates/single.html twentytwentyfive/templates/single.html
http
GET /
result
Fresh bread daily · 12 Market Street

get_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:

html
<!-- 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.

Check yourself

1. Which line in style.css makes a theme a child theme?
2. The child theme has parts/footer.html and the parent has one too. Which is used?
3. How is a child theme's theme.json combined with the parent's?
4. Why use a child theme instead of editing the parent?