If you have ever edited a theme file directly, hit “Update” on the parent theme a few weeks later, and watched your custom work vanish, you already understand why child themes exist. A child theme is a thin layer that sits on top of an existing theme and holds only your changes, so the parent can keep receiving security and compatibility updates without touching a single line of your work.
This guide shows you how to create a child theme in WordPress manually, with no generator plugin involved. You will end up with a folder containing two files, a proper stylesheet header, a correct enqueue function, working template overrides, and a testing routine that keeps your live site safe. We also included the part most tutorials skip: the situations where a child theme is the wrong tool and you should build something else instead.
What a Child Theme Actually Does (in 60 Seconds)
WordPress loads themes in a specific order. When a child theme is active:
- Templates: WordPress looks for a template file in the child theme first. If it is not there, it falls back to the parent. This is how you override
single.php,footer.phpor a block template without copying the whole theme. - functions.php: This file does not override the parent. Both files load, with the child’s
functions.phploading before the parent’s. It is additive. - style.css: Your child stylesheet loads after the parent’s, so your CSS wins on equal specificity.
- Updates: Updating the parent theme never overwrites the child folder.
That is the whole concept. Two files can create a valid child theme, and one of them is optional.

Before You Start: 4-Point Checklist
- Take a full backup (files + database) or work on a staging copy. Non negotiable.
- Confirm the parent theme is actively maintained. Building a child theme on an abandoned parent just postpones a bigger problem.
- Find the parent folder slug. Go to
/wp-content/themes/via FTP, SFTP or your host’s file manager and note the exact folder name (for exampletwentytwentyfive). Case sensitivity matters. - Identify the theme type. Does the parent folder contain a
templates/directory and atheme.jsonfile? Then it is a block theme. If it containsindex.php,header.php,footer.phpand friends, it is a classic theme. The steps differ slightly and we flag those differences below.
You will also need a plain text editor (VS Code, Sublime Text, Notepad++) and file access. Word processors will corrupt your files, so avoid them.
Step 1: Create the Child Theme Folder
Inside /wp-content/themes/, create a new folder. The convention is the parent slug plus -child:
/wp-content/themes/twentytwentyfive-child/
Rules that will save you a support ticket:
- No spaces, no uppercase letters, no special characters.
- Do not place the child folder inside the parent folder. They must be siblings.
- If you work with multiple client sites, use a brandable slug such as
acme-childso it is obvious in backups and logs.

Step 2: Create style.css With a Valid Header
Create a file named style.css in your new folder. The comment block at the top is what tells WordPress this is a theme, and the Template: line is what makes it a child theme.
/*
Theme Name: Twenty Twenty-Five Child
Theme URI: https://wptweety.org/
Description: Child theme of Twenty Twenty-Five. Holds all custom design work for this site.
Author: WPTweety
Author URI: https://wptweety.org/
Template: twentytwentyfive
Version: 1.0.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: twentytwentyfive-child
*/
/* Your custom CSS starts here */
The two lines that must be perfect:
Theme Name: any human readable name, must be unique on the install.Template: the exact folder name of the parent theme, not its display name.Twenty Twenty-Fivewill fail;twentytwentyfiveworks.
Everything else is metadata. If you get a “broken theme, the parent theme is missing” error, 95% of the time the Template value has a typo or the parent is not installed. The team at kinsta.com reached a similar conclusion.
Optional: add a screenshot
Drop a screenshot.png (1200 x 900 px) in the folder so the theme looks finished in Appearance > Themes. Purely cosmetic, but nice for client handovers.
Step 3: Enqueue the Stylesheets in functions.php
This is where most tutorials go wrong. Create functions.php in the child folder and add the following:
<?php
/**
* Twenty Twenty-Five Child: theme functions.
*/
add_action( 'wp_enqueue_scripts', 'wptweety_child_enqueue_styles', 20 );
function wptweety_child_enqueue_styles() {
$parent_style = 'parent-style';
$theme = wp_get_theme();
wp_enqueue_style(
$parent_style,
get_template_directory_uri() . '/style.css',
array(),
$theme->parent()->get( 'Version' )
);
wp_enqueue_style(
'child-style',
get_stylesheet_uri(),
array( $parent_style ),
$theme->get( 'Version' )
);
}
Why it is written this way:
- Never use
@importin style.css. It blocks parallel downloads and slows first paint. - The
array( $parent_style )dependency guarantees your CSS loads after the parent’s, so overrides work without!important. - Passing the theme version as the fourth argument gives you automatic cache busting. Bump
Version: 1.0.1in style.css and every visitor gets the fresh file. - Prefix your function names (
wptweety_) to avoid fatal “cannot redeclare function” errors.
Important exception for block themes
If the parent is a block theme, WordPress already loads both the parent and child style.css automatically. You do not need the enqueue code above, and adding it can double-load the parent CSS. For a block-theme child, a functions.php is only needed when you actually add PHP functionality.
Block themes: copy theme.json selectively
A child block theme can have its own theme.json. It is merged with the parent’s, not replaced, so only include the settings you are changing:
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"color": {
"palette": [
{ "slug": "brand", "color": "#0b5fff", "name": "Brand" }
]
}
}
}
Copying the parent’s entire theme.json is a classic mistake: it freezes hundreds of values and you lose every improvement the parent ships later.
Step 4: Activate and Sanity-Check
- Go to Appearance > Themes. Your child theme appears next to the parent.
- Hover it and click Live Preview first if the parent is a classic theme. For block themes, activate on staging instead.
- Click Activate.
- Load the front end. It should look identical to the parent. If it looks unstyled, your enqueue or your
Templateline is wrong.
Two things that do not transfer automatically when you switch themes, and that surprise everyone:
- Menu locations and widgets may need reassigning (Appearance > Menus, Appearance > Widgets).
- Customizer settings (logo, colors, layout options) are stored per theme in
theme_mods. Screenshot your settings before switching, or use an export/import tool, then re-enter them once.
Do this on staging and the checklist takes five minutes. Do it on a live homepage at 5pm on a Friday and it takes an hour of apologies.

Step 5: Override Templates the Right Way
Now the useful part. To modify a template, copy the file from the parent into the child, keeping the same relative path, then edit the copy.
Classic themes
twentytwentyfive-child/
├── style.css
├── functions.php
├── single.php (copied from parent, edited)
├── footer.php (copied from parent, edited)
└── template-parts/
└── content/
└── content-single.php
Block themes
Copy the HTML template into the same subfolder:
my-child/
├── style.css
├── theme.json
├── templates/
│ └── single.html
└── parts/
└── footer.html
Note that if you edit a template in the Site Editor, WordPress saves your version in the database, which takes priority over both theme files. To ship changes as code, use the Site Editor’s export feature and move the resulting files into your child theme, then clear the database customisations.
Path functions you must not mix up
| Function | Points to | Use it for |
|---|---|---|
get_stylesheet_directory() |
Child theme folder | Including your own files, your own assets |
get_template_directory() |
Parent theme folder | Referencing parent files (like its style.css) |
get_theme_file_path() |
Child first, parent as fallback | Files that may exist in either theme |
Changing parent PHP functions
You cannot “override” a parent function by redeclaring it unless the parent wrapped it in function_exists() (a pluggable function). Otherwise you get a fatal error. The safe patterns are:
// Remove a parent hook, then add your own.
add_action( 'after_setup_theme', 'wptweety_child_tweaks' );
function wptweety_child_tweaks() {
remove_action( 'parent_theme_footer', 'parent_theme_credits' );
add_action( 'parent_theme_footer', 'wptweety_child_credits' );
}
Use filters where the parent provides them. If it provides none and you need to rewrite core logic, that is a signal you may need a different approach (see the section below).
Step 6: Test Safely Before Going Live
Never build a child theme directly on production. Pick one of these three workflows, from best to acceptable:
- Local development. Tools like Local, Studio by WordPress.com, DevKinsta or Docker give you an offline clone. Fastest iteration, zero risk. Enable debugging in
wp-config.php:define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true ); define( 'WP_DEBUG_DISPLAY', false ); - Staging site. Most quality hosts offer one-click staging with push-to-live. Ideal because plugins and data match production.
- Live site with a theme switcher. If you truly cannot stage, a plugin such as Theme Switcha lets logged-in administrators view the child theme while visitors keep seeing the parent. Acceptable for small tweaks only.
Pre-launch QA list
- Homepage, a blog post, an archive, a search results page, a 404 page
- WooCommerce (if used): shop, product, cart, checkout, my account
- Contact and other forms actually send
- Mobile and tablet breakpoints
- Browser console clean of 404s and JavaScript errors
debug.logclean of PHP notices- Purge server, CDN and plugin caches, then hard refresh
Finally, put the child theme in version control. A child theme is code. Git gives you a rollback that no backup plugin can match in speed. More at https://developer.wordpress.org.
Child Theme vs Plugin vs Custom Theme: Choose the Right Container
| Your goal | Best tool | Why |
|---|---|---|
| A handful of CSS rules | Additional CSS / Global Styles | Update-safe already, no files to maintain |
| Design and template changes | Child theme | Exactly what it was designed for |
| Custom post types, shortcodes, integrations | Site-specific plugin | Functionality must survive a theme change |
| Same tweaks across many sites | Plugin or starter theme | Reusable and independently versioned |
| Unique design, full control, best performance | Custom theme | No parent overhead, no fighting inherited markup |

When a Child Theme Is the Wrong Choice
Child themes are excellent, but they are not free. You inherit the parent’s markup, its CSS weight, its assumptions and its bugs. Here are the honest red flags:
1. You are overriding more than half the parent
If your child folder contains 20 copied templates and 2,000 lines of CSS undoing parent styles, you are no longer customising. You are maintaining two themes at once. Every parent update becomes a manual diff session. At that point a custom theme or a lean starter theme (for example a block-based starter or an underscores-style base) is cheaper over 12 months.
2. The parent theme is abandoned or badly coded
No filters, no hooks, inline styles everywhere, last update 18 months ago? A child theme built on that foundation is technical debt with a nice name. Migrate instead.
3. You only need functionality, not design
Custom post types, REST endpoints, tracking scripts, business logic: put these in a small plugin. Bury them in a child theme’s functions.php and they disappear the day someone switches themes.
4. The design lives inside a page builder
With Elementor, Divi, Bricks or Beaver Builder, your layouts are stored in the database, not in template files. A child theme is still useful for code snippets and hooks, but it will not “protect” your designs, because those were never at risk from theme updates in the first place.
5. Performance is the primary KPI
A child theme loads the parent’s full CSS and JS, plus yours. On projects where Core Web Vitals drive revenue, shipping only the CSS you actually use in a purpose-built theme usually beats any amount of child-theme optimisation.
6. You want to make a child of a child
WordPress supports one level of inheritance only. Grandchild themes require custom code and are a maintenance trap. If you need multiple variations, use block style variations or separate child themes from the same parent.
Troubleshooting: The 6 Errors You Will Probably Meet
| Symptom | Likely cause and fix |
|---|---|
| “The parent theme is missing” | Wrong Template: value or parent not installed. Match the folder name exactly, including case. |
| Site loads unstyled | Parent CSS not enqueued (classic theme) or wrong handle. Re-check Step 3. |
| Child theme not listed | Missing or malformed style.css header, or folder nested inside the parent. |
| White screen after adding functions.php | PHP syntax error or duplicated function name. Check debug.log, rename with a prefix. |
| CSS changes not visible | Caching or specificity. Bump the theme version, purge caches, inspect the element. |
| Template edit ignored | Wrong file in the hierarchy, wrong subfolder path, or a database template from the Site Editor taking priority. |
FAQ
What is a child theme in WordPress?
A child theme is a theme that inherits all the templates, styles and functionality of another theme (the parent) and contains only your modifications. It requires a folder, a style.css with a Template: line pointing to the parent, and optionally a functions.php.
What is the difference between a parent theme and a child theme?
The parent theme is complete and works on its own. The child theme cannot work without the parent and only stores overrides. Updating the parent leaves the child untouched, which is the entire point. elementor.com walks through the specifics.
Can I create a child theme without a plugin?
Yes, and that is exactly what this tutorial covers. Two files and one folder. Generator plugins simply automate these steps, and several of them add extra options you never use.
Do I need a child theme if I only add a little CSS?
No. Use Appearance > Customize > Additional CSS on classic themes or the Styles panel in the Site Editor on block themes. Those values live in the database and already survive updates. Create a child theme once you need template or PHP changes.
Do child themes slow down a WordPress site?
The overhead is negligible: one extra stylesheet request and a slightly longer template lookup. What slows sites down is a bloated parent theme, not the child layer.
Does a block theme child need functions.php?
Only if you are adding PHP. WordPress automatically loads both parent and child style.css for block themes, so no manual enqueue is required.
What happens if I delete the parent theme?
The child theme breaks immediately. Keep the parent installed at all times, and keep it updated, because that is the security-relevant code.
Can I convert my existing customisations into a child theme?
Yes. Compare your modified parent files against a fresh copy of the same version, extract the differences, then place those changed files and CSS rules into the child theme. Do it on staging and test each page before switching.
Final Word
Knowing how to create a child theme in WordPress is a 15-minute skill that protects months of design work. Create the folder, write a correct style.css header, enqueue properly (or skip it on block themes), copy only the templates you need, and always test on staging before activating.
And keep the exit criteria in mind: the moment your child theme becomes bigger and messier than the parent it customises, stop patching and commission a proper custom build. Choosing the right container from day one is what separates a site that ages well from one that needs a rescue project every two years.

