Subtle diagonal pinstripe pattern in light grey and cream, giving an impression of printed editorial paper

Creating a Child Theme for a Custom WordPress Theme

A child theme gives you a controlled layer for modifying a WordPress theme without editing the parent theme’s original files. This is useful when a developer supplies a bespoke design, a studio maintains a private framework, or an agency has built a reusable theme for several client websites. Your changes remain separate, easier to audit and less likely to disappear when the parent theme receives maintenance updates.

The process is slightly different from creating a child theme for a popular public theme. A custom parent may use its own asset loader, template hierarchy, build process, theme.json settings, or naming conventions. Before adding files, inspect how the parent registers styles, loads JavaScript, declares template parts and handles translations. A child theme should extend those systems rather than accidentally competing with them.

This guide uses a practical workflow suitable for a development site, a WooCommerce build or a content website hosted in Australia. The same approach works whether the production server is in Sydney, Melbourne, Brisbane or Perth, provided you test PHP, caching and file permissions in an environment that matches the live site.

Inspect The Parent Theme First

Start by identifying the parent theme’s directory name, text domain and stylesheet header. These values are not always the same as the theme’s display name. Open wp-content/themes/your-parent-theme/style.css and look for a header similar to this:

/*
Theme Name: Harbour Custom
Text Domain: harbour-custom
Version: 1.4.0
*/

The directory name is important for the Template value in the child stylesheet. Check the parent’s functions.php for wp_enqueue_style(), wp_register_script(), custom hooks and filters. Search for functions such as after_setup_theme, wp_enqueue_scripts, register_block_type and register_nav_menus. This inspection reveals whether the parent expects a child theme to load a replacement stylesheet or whether it already exposes a suitable hook.

Review the parent’s templates before copying anything. WordPress searches the child directory first, so a file with the same relative path overrides the parent file. Copy only the template you need, such as single.php, archive.php, template-parts/content.php or a WooCommerce template. Copying the entire parent creates unnecessary maintenance work and makes future changes harder to trace.

For a custom theme maintained by a Sydney agency, record the parent version and commit identifier in your project notes. That simple habit helps when a client reports a layout change after deployment, particularly if development, staging and production servers have different cached assets.

Create The Child Theme Files

Create a new directory beside the parent theme. Use a clear slug, such as harbour-custom-child, rather than a display name containing spaces. A minimal child theme can begin with two files:

wp-content/
└── themes/
    ├── harbour-custom/
    └── harbour-custom-child/
        ├── style.css
        └── functions.php

Add the required metadata to style.css:

/*
Theme Name: Harbour Custom Child
Description: Child theme for the Harbour Custom theme
Author: Example Web Studio
Template: harbour-custom
Version: 1.0.0
Text Domain: harbour-custom-child
*/

Template must match the parent directory exactly, including capitalisation on systems where file names are case-sensitive. The child theme’s own Text Domain should be distinct if it contains translatable strings. Do not use the parent’s directory name in that field unless the project has a deliberate translation strategy.

The stylesheet header is enough for WordPress to recognise the theme, but it does not automatically make the parent’s CSS available in every modern setup. A child theme should explicitly enqueue its assets. Add this starting point to functions.php:

<?php

function harbour_custom_child_enqueue_styles() {
    wp_enqueue_style(
        'harbour-custom-parent',
        get_parent_theme_file_uri( 'style.css' ),
        array(),
        wp_get_theme( get_template() )->get( 'Version' )
    );

    wp_enqueue_style(
        'harbour-custom-child',
        get_stylesheet_directory_uri() . '/style.css',
        array( 'harbour-custom-parent' ),
        wp_get_theme()->get( 'Version' )
    );
}
add_action( 'wp_enqueue_scripts', 'harbour_custom_child_enqueue_styles' );

The parent handle and loading order may need adjustment. If the custom parent already enqueues its stylesheet, enqueuing it again can produce duplicate CSS. Inspect the page source and the parent code first. In some themes, the correct solution is to enqueue only the child stylesheet with the parent’s registered handle as a dependency.

Load Styles And Scripts Safely

CSS customisation should be incremental. Begin with a small rule that is easy to verify, such as a colour or spacing adjustment, then inspect the result in a private browser window. A child stylesheet might contain:

.site-header {
    background-color: #17324d;
}

.entry-content a {
    text-decoration-thickness: 0.12em;
}

Avoid copying the whole parent stylesheet into the child. That approach freezes old declarations and can override future fixes unintentionally. Use the browser’s developer tools to identify the source selector, then add the narrowest practical override. If a rule requires !important, document why it is needed and check whether the parent’s selector can be improved instead.

Scripts should be registered with a unique handle and loaded only where they are needed. For example:

function harbour_custom_child_scripts() {
    wp_enqueue_script(
        'harbour-custom-child',
        get_stylesheet_directory_uri() . '/assets/js/site.js',
        array(),
        wp_get_theme()->get( 'Version' ),
        true
    );
}
add_action( 'wp_enqueue_scripts', 'harbour_custom_child_scripts' );

Use get_stylesheet_directory_uri() for child files and get_parent_theme_file_uri() for parent files. This distinction prevents a common error where a child theme attempts to load an asset from the parent directory. If the site uses a build tool, enqueue the compiled file from dist, and keep source files outside the public asset path when the project’s deployment process supports that arrangement.

A Brisbane development team may test through a managed host with aggressive page caching, while a Melbourne developer may use a local Docker environment. In either case, clear WordPress, object, browser and CDN caches after changing asset versions. Versioning with the theme version or a file modification time helps browsers fetch the new file, but it should not replace proper cache invalidation during deployment.

Override Templates Without Breaking Updates

To customise markup, copy a parent template into the same relative location inside the child theme. For example, copy:

harbour-custom/template-parts/content.php

to:

harbour-custom-child/template-parts/content.php

Then edit the child copy. Keep the parent’s comments and template context while changing only the required markup. Template overrides can affect accessibility, structured data, pagination, post formats and plugin integrations, so compare the files again whenever the parent theme changes.

For a WooCommerce site, follow WooCommerce’s template override notices and keep a record of the template version. A child theme is not a licence to ignore compatibility warnings. If a custom parent includes a woocommerce directory, determine whether the parent has already modified a WooCommerce template before adding a second override in the child.

Requirement Recommended child-theme approach Common mistake
Parent CSS Enqueue it once, then load child CSS with a dependency Enqueueing the parent stylesheet twice
Custom styles Add focused selectors in style.css Copying the entire parent stylesheet
PHP changes Use hooks, filters and small functions Editing the parent functions.php
Template changes Copy only the required relative path Duplicating every parent template
JavaScript Use a unique handle and correct dependencies Loading scripts on every admin and front-end screen
Block settings Extend or replace theme.json carefully Assuming classic CSS controls all block styles
WooCommerce Check template versions after updates Ignoring notices in the WooCommerce status screen

PHP functions require special care. A child theme’s functions.php is loaded in addition to the parent’s file; it does not replace it. Never paste the parent’s complete functions.php into the child. Use a unique prefix such as harbour_custom_child_ to avoid collisions with the parent, plugins and WordPress core.

Hooks are generally safer than copying PHP implementation. For example, a child can change an excerpt length through a filter:

function harbour_custom_child_excerpt_length( $length ) {
    return 28;
}
add_filter( 'excerpt_length', 'harbour_custom_child_excerpt_length' );

If the parent does not expose a suitable hook, inspect whether a small template override or a carefully scoped filter is the better option. Keep business logic in a plugin when it must survive a theme change, such as custom post types, payment rules or site-wide data processing.

Handle Theme.json And Block Styles

Block themes and hybrid custom themes may use theme.json to define palettes, typography, spacing and layout settings. A child theme can include its own theme.json, but the result depends on the WordPress version and the theme’s architecture. Do not assume that a child file will merge every nested setting exactly as expected. Test editor controls and front-end output together.

A practical approach is to copy only the relevant configuration and validate it in the Site Editor or block editor. For example, a project may define a brand palette for an Australian hospitality client:

{
  "version": 2,
  "settings": {
    "color": {
      "palette": [
        {
          "slug": "coastal-blue",
          "color": "#17324d",
          "name": "Coastal Blue"
        }
      ]
    }
  }
}

Check whether the parent adds presets through PHP, CSS variables or its own JSON file. Duplicate declarations can create confusing editor behaviour, especially when a block’s inline styles take precedence over a stylesheet rule. Use the browser inspector and the editor’s generated markup to identify the actual source of a style.

Accessibility should be tested as part of the override. Australian sites commonly serve users on mobile connections across large distances, including regional areas outside capital cities. Keep CSS efficient, preserve visible focus states, maintain adequate colour contrast and avoid JavaScript interactions that fail when scripts are delayed or blocked.

Test The Theme Before Deployment

Activate the child theme on a staging site rather than changing production first. Test the home page, menus, search, archives, author pages, 404 responses, comments, forms and responsive breakpoints. If the site uses WooCommerce, test the shop, product variations, cart, checkout, account screens, transactional emails and any payment gateway return flow.

Test with the same PHP version and database mode used by the live server. A Perth host running PHP 8.2 may expose warnings that do not appear on a developer’s older local environment. Review the PHP error log, WordPress Site Health screen and browser console. Fatal errors in functions.php can prevent the theme from loading, so keep file access or a recovery method available while testing.

Check the child theme with debugging enabled in a non-production environment:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

Inspect wp-content/debug.log, but remove sensitive data before sharing logs with a contractor. If a front-end request or command-line task appears to hang, isolate the responsible hook, plugin or external request; process troubleshooting can also be relevant when diagnosing stalled execution outside ordinary template rendering.

Use browser tools to confirm that CSS and JavaScript return HTTP 200 responses. Check generated HTML for duplicate stylesheets, missing images and incorrect asset paths. Test at common widths rather than relying on a single laptop viewport. A client in Adelaide may review the same page on a phone over a variable mobile connection, so performance and graceful loading matter as much as visual accuracy.

Maintain The Child Theme Over Time

Keep the child theme under version control, even if it contains only two files. Commit related changes together, record the parent version being tested and separate layout fixes from dependency upgrades. A short changelog entry such as “Updated product archive override for parent 1.5.0” is more useful than a vague note saying “theme changes”.

After updating the custom parent, compare its changed files with every child override. Pay particular attention to template files, asset handles, function signatures, block patterns and WooCommerce integrations. A parent update may add a new accessibility attribute or security fix that the child copy does not contain. Merge the required change into the child rather than replacing the override blindly.

Keep environment-specific configuration out of the child theme. API keys, server paths and production-only constants belong in configuration or environment variables, not in a publicly accessible theme directory. Follow the same discipline for privacy-sensitive forms and analytics, particularly when an Australian business handles customer information under its privacy obligations.

Finally, document the activation process for the site administrator. Include the parent-child relationship, required plugins, build commands, cache-clearing steps and rollback method. This is valuable when a local council website, retail store or professional practice changes its maintenance provider. A well-structured child theme makes future work predictable: the parent supplies the foundation, while the child contains deliberate, reviewable customisations that can be tested and deployed safely.