How to create a child theme in WordPress with PHP in WordPress

Contents

Introduction — What is a WordPress child theme and why use one?

A child theme is a WordPress theme that inherits functionality, features and styling from another theme called the parent theme. Creating a child theme lets you safely customize and extend a parent theme without modifying the parent themes files directly. When the parent theme is updated, your customizations in the child theme remain intact.

This tutorial covers everything required to create a child theme using PHP (functions.php), proper enqueueing of styles and scripts, overriding templates, working with template hierarchy, advanced techniques (unhooking, overriding functions), localization, recommended file layout, debugging tips and best practices.

Prerequisites

  • WordPress installation (local or remote) with access to the theme folder (wp-content/themes).
  • Basic knowledge of PHP, CSS and WordPress theme file organization.
  • A code editor and an FTP / file manager or local access to the filesystem.

Overview of the child theme structure

At minimum a child theme requires a folder inside wp-content/themes and a style.css with the required header that points to the parent theme. In practice you usually add a functions.php to enqueue parent assets and to add custom PHP behavior. You can also add template files, image assets (screenshot.png), and JS/CSS files.

Typical child theme file/folder structure

  • my-child-theme/
  • nbspnbspstyle.css
  • nbspnbspfunctions.php
  • nbspnbspscreenshot.png
  • nbspnbspjs/
  • nbspnbspnbspnbspcustom.js
  • nbspnbspcss/
  • nbspnbspnbspnbspcustom.css
  • nbspnbsptemplates/ (optional template parts or page templates)

1) Create the child theme folder

  1. Open wp-content/themes/.
  2. Create a new folder. Use a short slug as the folder name, for example: twentytwentyone-child or mytheme-child. This folder name will be the themes directory name.

2) Create the style.css header

Create a file named style.css inside the child theme folder. The header at the top of style.css must include at least the Theme Name and the Template (the parent theme folder name). The Template value is case-sensitive and must match the parent theme directory name exactly.

Example of a valid style.css header:

/
Theme Name: My Theme Child
Theme URI: https://example.com/my-theme-child
Description: Child theme for My Theme
Author: Your Name
Author URI: https://example.com
Template: mytheme
Version: 1.0.0
Text Domain: mytheme-child
/

Notes:

  • Template is the parent theme directory name (for example: twentytwentyone or mytheme).
  • Do not rely on @import to load the parent stylesheet. Use enqueueing in functions.php for proper performance and compatibility.
  • For block themes or themes using full site editing, styles might be handled differently — but the child theme header still identifies the parent using Template.

3) Enqueue the parent and child styles properly in functions.php

Add a functions.php file to the child theme directory. This file is loaded in addition to the parent themes functions.php. The correct method to include the parent theme stylesheet is to enqueue it with wp_enqueue_style and then enqueue the child stylesheet with the parent as a dependency.

Recommended functions.php example (basic)

lt?php
/
  Child theme functions.php
  Enqueue parent and child theme styles correctly.
 /

function mytheme_child_enqueue_styles() {
    // Enqueue parent style.
    wp_enqueue_style( mytheme-parent-style, get_template_directory_uri() . /style.css )

    // Enqueue child style, make it dependent on parent style so its loaded after.
    wp_enqueue_style(
        mytheme-child-style,
        get_stylesheet_directory_uri() . /style.css,
        array( mytheme-parent-style ),
        wp_get_theme()->get(Version) // Version (optional).
    )
}
add_action( wp_enqueue_scripts, mytheme_child_enqueue_styles )

Important notes:

  • Use get_template_directory_uri() to reference the parent theme directory.
  • Use get_stylesheet_directory_uri() for items inside the child theme.
  • Do not place CSS import statements inside the child style.css header to load the parent style (the @import approach is deprecated for performance reasons).
  • If the parent theme already enqueues its stylesheet with a known handle, you can enqueue the child stylesheet with that handle in the dependency array for cleaner control.

Alternative: Load parent style using parent handle

If the parent theme registers its main stylesheet with a handle, you should use that handle to ensure proper ordering:

lt?php
function mychild_enqueue() {
    // Parent theme registered parent-style handle (example).
    wp_enqueue_style( child-style, get_stylesheet_uri(), array( parent-style ), wp_get_theme()->get(Version) )
}
add_action( wp_enqueue_scripts, mychild_enqueue )

4) Add child theme functionality (functions.php best practices)

The childs functions.php is loaded in addition to the parent themes functions.php, not instead of it. This means functions defined in the child do not override parent functions automatically. To modify or replace parent behavior, prefer hooks (actions/filters) and use remove_action/remove_filter or use higher priority.

Load translations from child theme

lt?php
function mytheme_child_setup() {
    load_child_theme_textdomain( mytheme-child, get_stylesheet_directory() . /languages )
}
add_action( after_setup_theme, mytheme_child_setup )

Register sidebars or add theme support (example)

lt?php
function mytheme_child_setup_features() {
    // Add theme support for post thumbnails if parent doesnt.
    add_theme_support( post-thumbnails )

    // Register an extra sidebar.
    register_sidebar( array(
        name          => __( Child Sidebar, mytheme-child ),
        id            => child-sidebar,
        description   => __( A sidebar registered in the child theme, mytheme-child ),
    ) )
}
add_action( after_setup_theme, mytheme_child_setup_features )

Replacing or modifying parent hooked functions

Preferred approach: unhook a parent callback and add your own. This avoids editing parent files.

lt?php
function mytheme_child_modify_parent_hooks() {
    // Ensure the parent has already added its actions, so run at a later priority.
    remove_action( wp_head, parent_theme_output_something )
    add_action( wp_head, mytheme_child_output_something )
}
add_action( after_setup_theme, mytheme_child_modify_parent_hooks, 20 )

function mytheme_child_output_something() {
    echo lt!-- Child theme custom head output --gt
}

Note: You must know the parent function name and hook priority to remove it reliably.

Overriding pluggable functions

Some themes declare functions wrapped in if ( ! function_exists( function_name ) ) { … } — these are pluggable and can be overridden by defining them in the child theme before the parent loads. This would require careful timing and is less common than using hooks.

5) Overriding template files

To override a parent template, copy the template file (for example header.php, single.php, page.php, template-parts/content.php, or archive.php) from the parent theme into the child theme and edit it. WordPress uses the child file instead of the parent file when it exists. Keep the path the same relative to the theme root.

  1. Locate the parent theme file you want to change (e.g., wp-content/themes/parent-theme/single.php).
  2. Copy it into wp-content/themes/your-child-theme/single.php (or the same subfolder structure if its under template-parts/).
  3. Edit the file in the child theme. The child file will be loaded instead of the parent file.

Key differences between get_template_directory() and get_stylesheet_directory()

  • get_template_directory(): returns the parent theme directory path (use when you want a file from the parent).
  • get_stylesheet_directory(): returns the active theme directory path — this is the child theme if one is active (use it to reference child theme assets).

Example referencing a file inside the child theme (useful in templates):

lt?php
// Include a PHP file from the child theme.
require_once get_stylesheet_directory() . /inc/custom-functions.php
?gt

6) Adding custom scripts and cache-busting

Enqueue JS and CSS with versioning. A common pattern for cache-busting during development is using filemtime to generate a version based on the file modification time.

lt?php
function mytheme_child_enqueue_assets() {
    // Child script path.
    child_js = get_stylesheet_directory() . /js/custom.js
    child_js_uri = get_stylesheet_directory_uri() . /js/custom.js
    version = file_exists( child_js ) ? filemtime( child_js ) : wp_get_theme()->get(Version)

    wp_enqueue_script( mytheme-child-js, child_js_uri, array( jquery ), version, true )
}
add_action( wp_enqueue_scripts, mytheme_child_enqueue_assets )

7) Adding template files such as page templates or template parts

You can add custom page templates inside the child theme. For classic page templates add the template file in the child and include the template header comment:

lt?php
/
  Template Name: Landing Page
  Description: Custom landing page template in child theme.
 /
get_header()
// ... markup ...
get_footer()
?gt

For newer block-based themes (full site editing), custom templates require different approaches (site editor templates or theme.json modifications), but the child theme can still include traditional template files for fallback behavior.

8) Localization and language files

To make your child theme translatable, create a /languages directory in the child theme and use load_child_theme_textdomain() as shown above. Use translation functions like __(), _e(), _x() with your child textdomain.

9) Screenshots and theme metadata

Add a screenshot.png in the child theme root. WordPress will display that image in the Appearance > Themes screen. The recommended size is 1200x900px, but older sizes (880×660) are acceptable depending on WP version.

10) Advanced topics

Overriding parent templates conditionally

Instead of replacing entire parent files, you can use filters and hooks inside the child theme to change behavior conditionally. For instance, filter the_content, change queries with pre_get_posts, or use template_include filter to swap templates:

lt?php
// Replace the template for a specific condition.
function mytheme_child_template_include( template ) {
    if ( is_singular( book ) ) {
        child_template = get_stylesheet_directory() . /single-book.php
        if ( file_exists( child_template ) ) {
            return child_template
        }
    }
    return template
}
add_filter( template_include, mytheme_child_template_include )
?gt

When you must edit parent functions (and alternatives)

Never edit parent theme files directly. If you must change behavior and the parent theme lacks appropriate hooks:

  • Contact the theme author asking for hooks/filters.
  • Use remove_action/remove_filter and re-add your implementation in the child theme.
  • Use plugin-based solutions for site-specific functionality that shouldnt live in a theme (recommended for portability).

Child theme and parent theme updates

Because all custom code and styling lives in the child theme, parent updates are safe. Always test updates in a staging environment. If a parent update changes template structure, your child overrides may require changes to stay compatible.

11) Debugging tips

  • Enable WP_DEBUG in wp-config.php during development to display PHP notices and errors.
  • Check the HTML source to verify styles and scripts are loaded in the expected order.
  • Use get_stylesheet_directory() and get_template_directory() to inspect file paths while debugging (temporary var_dump or error_log calls).
  • If a child template doesnt load, verify the copied file path exactly matches the parent structure and that the child theme is activated.

12) Example: A complete minimal child theme

Below is a minimal but complete example showing style.css and functions.php for a child theme called My Theme Child whose parent theme folder is mytheme.

style.css

/
Theme Name: My Theme Child
Theme URI: https://example.com/my-theme-child
Description: Child theme for My Theme
Author: Your Name
Author URI: https://example.com
Template: mytheme
Version: 1.0.0
Text Domain: mytheme-child
/

/ Custom child theme styles go below /
body {
    background-color: #f9f9f9
}

functions.php

lt?php
/
  My Theme Child functions.php
 /

// Enqueue parent and child styles.
function mytheme_child_enqueue_styles() {
    // Parent style.
    wp_enqueue_style( mytheme-parent-style, get_template_directory_uri() . /style.css )

    // Child style depends on parent style.
    wp_enqueue_style(
        mytheme-child-style,
        get_stylesheet_uri(),
        array( mytheme-parent-style ),
        wp_get_theme()->get(Version)
    )
}
add_action( wp_enqueue_scripts, mytheme_child_enqueue_styles )

// Add sample functionality: custom logo support.
function mytheme_child_custom_setup() {
    add_theme_support( custom-logo )
}
add_action( after_setup_theme, mytheme_child_custom_setup )
?gt

13) Security and performance considerations

  • Sanitize and escape data when adding custom theme options or outputting data (use esc_html, esc_attr, esc_url, wp_kses, etc.).
  • Load only the scripts and styles you need dequeue unnecessary assets when possible.
  • Follow WordPress coding standards for better maintainability.

14) Full checklist before deploying a child theme to production

Checklist item Action
Child folder created Folder exists in wp-content/themes/ and has correct name.
style.css header Includes Theme Name and Template (parent directory name).
Parent stylesheet enqueueing Parent stylesheet enqueued in functions.php (no @import).
Custom functions Added to child functions.php using hooks avoid redefining parent functions.
Template overrides Copied template files placed in child preserving path tested.
Localization load_child_theme_textdomain used and .pot/.po/.mo files present if needed.
Security Data sanitized and escaped.
Performance Unneeded scripts/styles removed or deferred, versioning applied for cache-busting.
Backup Child theme files backed up before going to production.

15) Common pitfalls and how to avoid them

  • Using @import in style.css: Avoid it. Use wp_enqueue_style in functions.php to load the parent stylesheet.
  • Wrong Template name in header: Ensure Template exactly matches the parent theme directory name (case-sensitive).
  • Expecting child functions.php to replace parent functions: It does not. Use hooks or remove_action/remove_filter to modify behavior.
  • Trailing whitespace after PHP closing tag: Its best practice to omit the closing ?> in PHP-only files to avoid accidental whitespace output.

Conclusion

Creating a child theme is the recommended way to customize a WordPress theme safely. Use a child theme to override templates, enqueue additional styles/scripts, add new features, and keep your changes separate from the parent theme so updates are safe. Follow best practices: enqueue parent and child styles correctly, use hooks and filters to alter behavior, and keep security and performance in mind.

For many advanced or site-specific functions, consider using a small custom plugin so important functionality survives theme changes. For everything theme-related, keep your custom templates and presentation in the child theme.



Acepto donaciones de BAT's mediante el navegador Brave 🙂



Leave a Reply

Your email address will not be published. Required fields are marked *