Howto: WordPress Child Themes

Last week, I had to make some HTML/CSS/PHP changes to a wordpress blog. I remembered, that the last time I made something like that, all of my changes made directly to the running theme have been overwritten by a theme update. So this time, I really wanted to make things right, make it the wordpress way. A couple of searches revealed this article.

The basic concept here is to create a child theme that inherits your current theme, where you have extra instances of all the files you want to make changes to. Here’s an example: Let’s assume you want to make changes to the theme file archive.php. You’d create a child theme, copy archive.php to that child theme and make your changes there. If there’s an update available for your theme, this will only affect the files from the base/parent theme and all your changes will remain untouched. The article above is pretty straight forward. However, I’ve had some issues with it and I’ll tell you where.

1. Create a child theme

The first step is to create a directory for your child theme in /wp-content/themes/. Let’s assume, the theme you want to inherit is called foo-theme, I’d recommend to call the child theme foo-theme-child. So You’d have to create /wp-content/themes/foo-theme-child. Place two files in that new directory: style.css and functions.php, both are necessary.

2. Edit style.css

The child theme’s style.css should have the following content:

/*
 Theme Name:   Foo Theme Child
 Theme URI:    http://some.url/
 Description:  Foo Child Theme
 Author:       John Doe
 Author URI:   http://example.com
 Template:     foo-theme
 Version:      1.0.0
 License:      GNU General Public License v2 or later
 License URI:  http://www.gnu.org/licenses/gpl-2.0.html
 Tags:         light, dark, two-columns, right-sidebar, responsive-layout, accessibility-ready
 Text Domain:  foo-theme-child
*/

Which basically is just a comment, but it contains two important things, the name of the parent theme (Template: foo-theme) and the name of the child theme (Text Domain: foo-theme-child)! So this is part of the way you tell wordpress the inheritance.

3. Edit functions.php

Now, here’s what the article above suggests to do in your child’s functions.php:

<?php
function my_theme_enqueue_styles() {
 
    $parent_style = 'foo-theme';
    $child_style  = 'foo-theme-child';
 
    wp_enqueue_style( $parent_style, get_template_directory_uri() . '/style.css' );
    wp_enqueue_style( $child_style,
        get_stylesheet_directory_uri() . '/style.css',
        array( $parent_style ),
        wp_get_theme()->get('Version')
    );
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );
?>

The idea behind this is to use the wordpress hook add_action to ensure the correct order that the parent’s and child’s themes are included. This is important, because the child theme’s CSS needs to be enqueued last, so that it overwrites all of the parent’s CSS. So, in the hook-function my_theme_enqueue_styles(), it uses wp_enqueue_style() to include the parent’s and then the child’s CSS afterwards.

4. Why that could fail

According to this post and my observations, the child’s functions.php will be called before the parent’s. If the parent also enqueues its own CSS files, those will again overwrite the child’s CSS. Which is exactly what happened in my case, resulted in the following inclusion order:

  1. Parent (from child’s functions.php)
  2. Child (from child’s functions.php)
  3. Parent (from parent’s functions.php)

So the parent’s CSS always came last (again) and overwrote all the stuff from the child.

5. What you can do about it

Check your parent theme’s functions.php for occurrences of wp_enqueue_style(). If you can find something, it’s possible for you to run into the same issue.

Here’s what I did about it:

  • In the child’s function.php remove the first wp_enqueue_style(), because there’s simply no need to enqueue the parent’s CSS again
  • Add a priority to the call of add_action()(see the help) to ensure, that the child’s function.php is called last. In the help you can see that the default is a priority of 10. I simply used the constant PHP_INT_MAX, just to make sure 🙂

Here’s my resulting functions.php of the child theme:

<?php
function my_theme_enqueue_styles() {
 
    $child_style  = 'foo-theme-child';
    wp_enqueue_style( $child_style, get_stylesheet_directory_uri() . '/style.css');
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles', PHP_INT_MAX );
?>

If you have any questions on that, send me a message!