iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Child Themes

A child theme inherits from a parent theme and lets you override templates, styles, and functions without editing the parent — so the next parent update doesn’t blow away your changes. Required for any production WordPress site that customises a third-party theme.

style.css, functions, overrides, FSE

EXAMPLE
<?php
// 1) Directory layout
//   wp-content/themes/
//     parent-theme/                       (the theme you bought / downloaded)
//     parent-theme-child/                  (your child theme)
//       style.css
//       functions.php
//       screenshot.png                      (optional preview)
//       templates/                          (FSE overrides)
//       parts/                              (FSE template parts)

// 2) Minimum child theme — classic theme
// parent-theme-child/style.css
/*
 Theme Name:   Parent Child
 Theme URI:    https://example.com/parent-child
 Description:  Child theme of Parent
 Author:       Mara
 Author URI:   https://example.com
 Template:     parent-theme            <-- exact directory name of the parent
 Version:      1.0.0
 License:      GPL-2.0-or-later
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html
 Text Domain:  parent-child
*/

// 3) functions.php — enqueue parent + child styles correctly
add_action( 'wp_enqueue_scripts', function () {
    $theme  = wp_get_theme();
    $parent = $theme->parent();

    // Parent stylesheet
    wp_enqueue_style(
        'parent-style',
        get_template_directory_uri() . '/style.css',
        array(),
        $parent->get( 'Version' )
    );

    // Child stylesheet (depends on parent)
    wp_enqueue_style(
        'child-style',
        get_stylesheet_uri(),                        // returns the CHILD theme's style.css
        array( 'parent-style' ),
        $theme->get( 'Version' )
    );
} );

// IMPORTANT: child stylesheet declares 'parent-style' as a dependency so it loads AFTER.

// 4) Override a template — copy + customise
// Parent file:  parent-theme/single.php
// Child file:   parent-theme-child/single.php          <-- WordPress picks the child's version

// Same for: page.php, archive.php, header.php, footer.php, sidebar.php, comments.php
// Including arbitrary template parts loaded via get_template_part()

// 5) Override a template part (more robust than copying the whole template)
// In the parent: get_template_part( 'template-parts/content', 'page' );
// Just create: parent-theme-child/template-parts/content-page.php — WordPress prefers child

// 6) Add a custom template (page template)
// parent-theme-child/templates/landing.php
<?php
/**
 * Template Name: Custom landing
 */
get_header(); ?>
<main class="landing">
    <?php while ( have_posts() ) : the_post(); the_content(); endwhile; ?>
</main>
<?php get_footer(); ?>

// Editors can now select 'Custom landing' from Page Attributes -> Template.

// 7) Override or extend functions.php
// • Child functions.php runs BEFORE parent functions.php
// • Parent functions still run UNLESS you remove/override their hooks

// Add a feature
add_action( 'after_setup_theme', function () {
    add_theme_support( 'custom-units', array( 'rem' ) );
} );

// Remove a parent action
add_action( 'init', function () {
    remove_action( 'wp_head', 'wp_generator' );
}, 11 );

// Replace a parent filter
add_filter( 'excerpt_length', function () { return 30; }, 20 );    // override parent's default

// 8) Override a pluggable function
// If the parent defines its function in a pluggable wrapper:
// if ( ! function_exists( 'parent_logo' ) ) { function parent_logo() { … } }
// In the child, define BEFORE the parent loads:
function parent_logo() { /* your version */ }

// 9) Add child-only scripts
add_action( 'wp_enqueue_scripts', function () {
    $theme = wp_get_theme();
    wp_enqueue_script(
        'child-extras',
        get_stylesheet_directory_uri() . '/assets/extras.js',
        array( 'jquery' ),
        $theme->get( 'Version' ),
        array( 'in_footer' => true )
    );
} );

// 10) Block themes (FSE — Full Site Editing) — child overrides
// Parent theme has templates/ as .html files. Child overrides by placing the same file.
//
// parent-theme/templates/single.html             — parent
// parent-theme-child/templates/single.html        — child (wins)
//
// theme.json overrides — duplicate the file and modify; WP merges parent + child
//   parent-theme/theme.json
//   parent-theme-child/theme.json
//
// Within theme.json, child values are MERGED into parent (deep merge for objects).

// 11) Useful helper functions
// get_template_directory()          -> /path/to/parent-theme
// get_template_directory_uri()      -> https://site/wp-content/themes/parent-theme
// get_stylesheet_directory()        -> /path/to/parent-theme-child
// get_stylesheet_directory_uri()    -> https://site/wp-content/themes/parent-theme-child
// get_stylesheet_uri()              -> https://site/wp-content/themes/parent-theme-child/style.css

// 12) Translation files
// parent-theme-child/languages/parent-child-en_AU.po
// In functions.php:
add_action( 'after_setup_theme', function () {
    load_child_theme_textdomain( 'parent-child', get_stylesheet_directory() . '/languages' );
} );

// 13) Workflow tips
// • Version your child theme — bump version on every release to bust cache
// • Use a child theme generator (Astra, Ocean, Generate) for a quick start
// • Keep customisations small + commented; large overrides hint that the parent isn't a good fit
// • Use Composer + autoloading for complex PHP logic — child themes are essentially packages

// 14) Common bugs
// • Forgot 'Template:' header in style.css — child theme appears broken
// • Used @import in style.css instead of wp_enqueue_style — slow + deprecated
// • Forgot dependency on parent-style — child CSS loads BEFORE parent, gets overridden
// • Template hierarchy not picking the child's file — file name mismatch (case-sensitive on Linux)
// • theme.json conflicts between parent + child — review with Site Editor preview
// • Child uses get_template_directory() for its own assets — that's the PARENT's path
// • Plugin loaded as a 'must-use' overrides child theme — order matters
// • Editing parent directly 'just for a quick fix' — next parent update wipes it

Why it matters

Always customise a third-party theme through a child theme — never edit the parent. Override templates by file name, enqueue parent and child stylesheets in the right order, and use FSE-style theme.json overrides for block themes. Future-you (and your update workflow) will thank present-you.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Inherits parent's templates; override file by file.
// style.css: Template: parent-theme-slug
Try it Yourself »

Discussion

Loading…