How Child Themes Work and When They Don’t
Since Child Theme Configurator was released on WordPress.org in November of 2013, thousands of users have created child themes on their WordPress sites with the free Child Theme Configurator plugin.
Having helped hundreds of users to get all kinds of themes to work, we have seen over and over again that when there is a problem, it is usually because the theme did not follow basic guidelines.
If you have tried all of the suggestions below and continue to have trouble making child themes work, download and run the WordPress Theme Check plugin and contact the theme author if it does not pass.
This tutorial boils how child themes work down to seven points:
- A child theme is not simply a modified copy of another theme. It is a special feature of WordPress that lets you override specific styles and functions of another theme.
- WordPress first checks for files in the active theme. If the active theme is using another theme as a parent, WordPress then checks for files in the parent theme (and the active theme officially becomes a “child” theme).
- The terms “stylesheet” and “template” have specific meanings when referring to parent or child themes.
- Themes and plugins should use the “wp_enqueue_scripts” action so WordPress can control the order in which stylesheets and scripts are loaded.
- The Active theme’s “style.css” file should be loaded last, whether or not it is used by the theme.
- Some themes and plugins do not follow WordPress guidelines, but there may be workarounds.
- No theme can do everything you want. Nor should it.
1. A child theme is not simply a modified copy of another theme. It is a special feature of WordPress that lets you override specific styles and functions of another theme.
Both the child theme and the parent theme must be installed, and the child theme must be activated.
The “active” theme is the theme currently being used for the live WordPress site, whether or not it is a “child” theme. Being a child theme that references another “parent” theme does not mean WordPress will automatically use it as the “active” theme.
Most of the execution occurs in the parent theme, but the child theme may change certain styles and functions to provide a different appearance or interface.
Why this affects how child themes work:
- A child theme does not function on its own. It requires another inactive theme to be installed to act as its “parent” theme.
2. WordPress first checks for files in the active theme, then checks for files in the parent theme.
In order for WordPress to be able inherit styles and functions from another “parent” theme, it needs to be able to read files from both themes, but treats the child theme as the “active” theme.
WordPress first reads the active theme’s stylesheet (style.css
) to get the theme’s “header” properties. It then checks if the theme has a functions file (functions.php
) and executes it if it exists.
If the theme’s “header” properties indicate another theme should be used as a parent it then looks for a functions file in the parent theme and executes it as well.
This is the key to how child themes work: two theme directories are checked for files, first the “active” or “child” directory, then the “parent” directory.
Next, WordPress determines the “template” to use based on the nature of the web site request. Once it decides the type of output to render, it first checks the active theme directory for the most appropriate “template” file.
If it does not find it there, and the active theme is a child theme, it then checks the parent theme directory for an appropriate “template” file. Read more about how WordPress determines the most appropriate “template” file for the job.
WordPress begins to render the template file, executing instructions as it goes. Each time an additional template is required, WordPress checks the theme directories, first the child, then the parent, for the most appropriate match and runs it.
Throughout this process, WordPress fires various “actions” that branch off to other sections of code. Section 4 explains how actions are used with themes to control stylesheets and scripts.
Why this affects how child themes work:
- WordPress will use the child version of a template if it exists. This means you can customize the child version without changing the parent version.
- WordPress will use the parent theme template if it does not exist in the child theme. This means you only need to create child theme templates you want to customize.
- The child theme runs first so you can “override” specific functions in the child theme functions file (assuming the parent functions are coded correctly, see section 6).
3. The terms “stylesheet” and “template” have specific meanings when referring to parent or child themes.
Stylesheet
We normally use the term “stylesheet” to mean “a CSS file that defines how elements should be drawn by the browser.” However, in the context of WordPress themes, “stylesheet” refers to “the active theme’s directory name inside the theme root.”
For example, if “Twenty Fifteen” is the active theme, the function get_stylesheet()
would return “twentyfifteen”. get_stylesheet()
always returns the active theme’s directory name inside the theme root whether or not the active theme is a child theme.
Template
We usually use the term “template” to mean “a PHP file used to render output sent to the browser.” Often a single response is the combined result of several templates.
Unfortunately, in the context of WordPress themes, “template” refers to “the theme used as a parent, or fallback theme.” It is a specific “header” property used in a theme’s style.css
file. It is also what makes WordPress consider a theme to be a “child” theme.
The function get_template()
returns the parent theme’s directory name inside the theme root if the active theme is a child theme, but returns the active theme’s directory name otherwise.
Read more about confusing WordPress theme function names and “header” properties.
Why this affects how child themes work:
- “Stylesheet” refers to the “child” or “active” theme when describing a theme directory.
- “Template” refers to the “parent” theme when describing a theme directory.
- For the purpose of this tutorial, only the terms “parent,” “child” or “active” are used to describe themes. The term “template” always refers to a PHP file used to render output to the browser, and “stylesheet” always refers to specific a CSS file.
4: Themes and plugins should use the “wp_enqueue_scripts” action to load stylesheets.
WordPress was designed to be extended. One way it accomplishes this is through the WordPress Plugin API, using “actions.” An “action” is a queue (list) of functions to be run at a specific point in the WordPress program flow. Each action is like a miniature program that is created on-the-fly as WordPress runs.
Themes and Plugins can add functions to an action queue and they will be run in order of priority when when WordPress executes that particular action. By default, they will run in the order they were added to the queue.
The priority can be set to a specific value to place it higher or lower in the queue. This allows Themes and plugins to influence when a function runs in relation to other functions in the program flow.
The most important action when it comes to loading stylesheets and scripts is the “wp_enqueue_scripts” action. As WordPress runs, themes, plugins and other components add functions to this action so that they are all output to the browser in a controlled sequence at one time.
Using the wp_enqueue_scripts
action allows a child theme to override the default styles of the theme, thereby customizing the appearance. This is explained in more detail in the next section.
Some themes still hard-code stylesheet links into the template file. As a result WordPress cannot control the order stylesheets load which leads to other issues. This is discussed in more detail in section 6.
Why this affects how child themes work:
- Using
wp_enqueue_scripts
to load stylesheets and scripts is recommended because it allows WordPress to optimize the load order and prevent conflicts. - This method also allows themes and plugins to influence how stylesheets and scripts load in relation to one another.
- Hard-coding stylesheet links in the header template causes stylesheets to load in the wrong order (see section 6)
5. The Active theme’s “style.css” file should be loaded last, whether or not it is used by the theme.
Some themes do not use the conventional style.css
file for their styles. Although this is perfectly acceptable, the theme should enqueue the active theme’s style.css
anyway to enable the styles to be customized by a child theme.
Even if a theme does not load the active style.css
file, Child Theme Configurator provides ways to make it work.
What does CSS Mean?
CSS is short for “Cascading Style Sheets”, a language that defines how elements are drawn on in the browser. As CSS is read from top-to-bottom, rules “cascade” down to the rules below them, in other words, rules that are defined later “inherit” the rules defined earlier.
This also applies to multiple stylesheets as well. For example, lets assume a web page uses two stylesheets. In the HTML, suppose they are loaded like this:
<link rel="stylesheet" src="/path/to/stylesheet1.css" />
<link rel="stylesheet" src="/path/to/stylesheet2.css" />
This means that the rules in stylesheet2.css inherit the rules in stylesheet1.css. In addition, rules in stylesheet2.css take priority, or “override,” rules in stylesheet1.css.
Therefore, the rules in stylesheet2.css are the “final word” for how elements are drawn, but any rules in stylesheet1.css will be used if they are not defined in stylesheet2.css.
CSS in WordPress
The example above is important because in order to be able to change the rules of a style, the changed rule must load after the style being changed. (Unless you use !important, you may be thinking.)Therefore, WordPress must be able to load first the parent styles, then the child styles, in that order, so that the CSS “cascades” correctly.
This can be accomplished several ways, but three are commonly used:
- The Child theme enqueues the Parent stylesheet, then the Parent theme enqueues the active (child) theme’s stylesheet. This is compatible with most themes, and is the default method used by Child Theme Configurator.
- The Parent theme enqueues the parent stylesheet if the active theme is a child theme, and then enqueues the active (child) theme’s stylesheet. As suggested by Justin Tadlock, this is the ideal solution, but is not used as often as it should.
- The Parent theme enqueues the active (child) theme’s stylesheet, which uses
@import
to load the parent stylesheet before loading the rest of the stylesheet. This method is no longer recommended.
Child Theme Configurator provides several options to handle loading the stylesheets.
Tutorial: Stylesheet Handling
This video tutorial shows how to determine the appropriate stylesheet handling option to use and troubleshoot common theme stylesheet issues View Video
Why is @import no longer recommended?
Linking stylesheets allows the browser to load stylesheets asynchronously (at the same time) while @import
“blocks” (makes the browser wait before loading the rest of the code). This can lead to slower load times, search engine penalties and the dreaded Flash of Unstyled Content.
In 2009, Steve Souders published Don’t Use @import, which uses browser timelines to illustrate the speed differences of @import
instead of or in combination with link.
Aside from that, WordPress cannot control the order stylesheets are loaded when a stylesheet imports another stylesheet. Any styles in the imported file immediately take priority over styles loaded before it and this may have unintended consequences.
However, because some themes hard-code the stylesheet link in the template file, the common practice to ensure the active stylesheet was able to override the parent stylesheet was to use @import
to import it via the active stylesheet. This is why, until recently, @import
was recommended for child themes.
Child Theme Configurator provides several “stylesheet handling” options to solve this problem without using @import.
Child Theme Configurator still provides option to use the older @import
method, but it should only be used if absolutely necessary.
Why this affects how child themes work:
- Stylesheets inherit from and take priority over styles loaded before them by the browser.
- For a child theme to control the styles of a site, the active stylesheet must load after the other stylesheets.
- Child Theme Configurator provides several options for handling stylesheets depending on the way the theme is written.
6. Some themes and plugins do not follow WordPress guidelines, but there may be workarounds.
WordPress has evolved quickly in recent years, and methods that were common practice before have been replaced by newer, better practices.Themes that are listed in the theme repository on WordPress.org undergo a thorough vetting process and in our experience we see the most issues with “premium” themes. Even so, any theme can have issues, and Child Theme Configurator provides ways to work around common problems.
The most common theme mistakes that prevent child themes from working:
-
Using
get_stylesheet_directory()
to build any include path.This will cause WordPress to crash with a Fatal Error if the included file does not exist in the child theme. A child theme can “hook into” the parent theme, but the parent theme should never require child theme files other than the stylesheet. If you see “No such file or directory” or “Failed opening for inclusion” errors, this is often the cause.
A child theme should work with nothing more than a
style.css
file with the “Template” header parameter set to a parent theme. If your theme or “framework” requires certain files or directories to be present in child themes, it is time to look for another theme. -
Placing the
wp_head()
anywhere except just before the closing</head>
tag.Linking stylesheets or scripts after the
wp_head
action will almost always cause them to load in a way that no child theme or plugin can override them using actions (see wp_head() in the Codex).If you find yourself in this scenario, try copying the
header.php
to the child theme using the Files tab and manually editing it so that thewp_head()
function call appears just before the</head>
tag. You can then set the appropriate stylesheet handling option on the Parent/Child tab. -
Hard coding stylesheet link urls into the
header.php
template instead of usingwp_enqueue_scripts
in a theme function.Because the linked stylesheets load before WordPress outputs the enqueued stylesheets, the child theme cannot link the parent styles ahead of the active stylesheet.
Child Theme Configurator provides a stylesheet handling option to work around this problem. By selecting “Enqueue both parent and child stylesheets,” the child theme will first enqueue the parent stylesheet, then enqueue the active theme stylesheet later in the program flow. This allows the active theme stylesheet to override styles in the parent theme stylesheet without using
@import
. See Determining which stylesheet handling option to use in the Child Theme Configurator documentation. -
Using
get_bloginfo( 'stylesheet_directory' )
orget_stylesheet_directory_uri()
to load any stylesheets or scripts other thanstyle.css
.This works fine as a standalone theme, but when used as a parent theme, all of the links will point to files that do not exist in the child theme.
-
Using
get_template()
orget_bloginfo('template_url')
instead ofget_stylesheet_uri()
to link the theme stylesheet.Even if correctly enqueued, WordPress will never load the child theme stylesheet if used as a parent theme. Use the “Enqueue child stylesheet” option in CTC to enable the child theme styles.
-
Using a closing PHP tag (?>) at the end of a file.
While this will not throw a fatal error, it directs anything that follows to the browser. This can lead to unexpected behavior, particularly if it occurs prior to the http header.
-
Loading
style.css
before other stylesheetsSelecting the “Enqueue parent stylesheet” option in CTC will work, but you will not be able to customize any stylesheets that load after
style.css
. -
Not loading
style.css
at all.This is easily fixed by selecting the “Enqueue child stylesheet” option in CTC to enable the child theme styles.
-
Not wrapping functions in
if !(function_exists()))
This means the theme functions cannot be overridden by a child theme. This is not a major concern unless you plan to make significant changes to the PHP, in which case you should probably use a different theme.
Why this affects how child themes work:
- Some themes will not work as parent themes without modifications.
- Child Theme Configurator provides workarounds for many common issues with child themes.
7. No theme can do everything you want. Nor should it.
In our experience, trying to be “one size fits all” actually makes a theme less useful. The more features that are built into a theme, the more complicated the interface gets, the slower the site runs, and the buggier the code becomes. If your “premium” theme is larger than 5MB zipped, it may be too bloated to perform well.
In some cases, commercial themes and “frameworks” override so much core functionality that it makes it impossible for plugins to work correctly. They “infringe on the plugin domain” and end up making your site harder to customize.
A child theme allows you to start with a well designed, stable theme that is not overloaded with bells and whistles and then work in the needed features yourself with plugins. A child theme lets you create the site you want by extending an existing WordPress theme with your own personal touch.
Most importantly, a child theme does not restrict you to the few custom options the theme provides. It becomes a blank canvas on which you can paint anything you want, and Child Theme Configurator helps you make child themes work.
Resources for How Child Themes Work
- WordPress Child Themes (Codex)
- WordPress Theme Testing Process
- Theme Check Plugin
- WordPress Template Hierarchy (Codex)
- WordPress Plugin API (Codex)
- Sarah Gooding, 7 Deadly Sins of WordPress Development
- Justin Tadlock, Loading parent styles for child themes
- Steve Souders, Don’t Use @import