How to overwrite WordPress themes safely?

One of the activities that is performed on almost every website that uses themes is customizing them.

We can split these modifications in two groups:

  1. small CSS changes in theme
  2. complex changes not only in CSS but in the structure of HTML

In this post I’ll try to show how to properly overwrite themes.

Why you shouldn’t modify a theme?

You have to remember that every theme is a piece of software which is (generally speaking) being developed by its author all the time. It means, that every theme can get fixes regarding:

  • security
  • support for WordPress updates
  • support for plugins’ updates
  • bug fixes for issues raised by the author or other users
  • new theme features

Therefore, abandoning the possibility of updating the theme brings certain risks. These risks can relate to security, problems after an update of WordPress and plugins. Moreover, you can lose access to bug fixes and new features.

Mostly, huge changes in theme are a reason of this abandoning. Why? Because implementing these changes again would involve too big of an effort. Fortunately, WordPress provides simple solutions to this problem.

Simple appearance modifications through CSS

When you need to change only the themes’ CSS it makes no sense to overcomplicate things. You just need a right plugin, which adds your CSS to your theme. Thanks to this, your CSS code will be independent of theme updating - unless the theme changes will be so significant that your CSS code will simply require changes. But for now, we don’t know any other option to bypass these issues.

To create your own CSS code I recommend to use one of the following:

Custom CSS module from JetPack plugin

jetpack wordpress

Custom CSS module is quite a powerful tool to create your own CSS. It supports CSS preprocessors and code revisions. This is certainly one of the best solutions on the market right now. But it has one considerable difficulty - it requires the whole JetPack plugin installation. Unfortunately, the alternative solution - which was the plugin JP Custom CSS is no longer supported (it was a Custom CSS module extracted from JetPack).

Simple Custom CSS

simple custom css

This plugin allows you to add your own CSS code to your website. It has a code field and ‘save changes’ button. I recommend it, in case you don’t need other modules of JetPack plugin. It simply makes no sense to install the whole JetPack plugin only for one feature.

Child Themes

A child theme is is a theme that overwrites only a selection of files from its parent. This usually means it’s a rather simple “overlay” on top of the original theme.

How to create a Child Theme

To create a child theme you need to create a new directory under wp-content/themes/ and name it THEME_NAME-child (the suffix could be different; it isn’t necessary to create a directory with the -child suffix, but it is very commonly used and highly recommended as it makes it clear to other programmers that you are using a child theme of a particular theme) and within that directory you add a file called style.css.

Add the following code to style.css:

/*
Theme Name: Parent Theme Child
Template: parent-theme
Version: 1.0.0
Text Domain: parent-theme-child
*/

/* Load the CSS code from the base theme */
@import url('../parent-theme/style.css');
/* Insert your own CSS code below */

With a basic file like this, you can start adding your own CSS code to style the theme to your liking. It is important to remember that the first thing this snippet does is to import all the CSS declarations from the parent theme.
In the line:

Template: parent-theme

You have to specify the name of the base theme’s directory - this is how WordPress will know where should it import the information about all the files from. The other fields you should fill with information related to the child theme. For example, if you want to create a child theme for the standard Twenty Fifteen theme, you need to create a twentyfifteen-child directory with a style.css file that contains the following code:

/*
Theme Name: Twenty Fifteen Child
Template: twentyfifteen
Version: 1.0.0
Text Domain: twentyfifteen-child
*/

/* Load CSS code from a base theme */
@import url('../twentyfifteen/style.css');

/* Insert your CSS code below */

You may also include other parameters like: child theme’s author or a link to a child theme’s page.

I use the @import function because it is the easiest solution, but this function is not the perfect solution when it comes to the performance of loading CSS files. If you would rather avoid using the @import function to load CSS code from a parent theme, you may use another method - you could create a functions.php file in your child theme directory and then add the following code to it:

if(!function_exists('child_theme_css')) :
   function child_theme_css() {
      wp_enqueue_style('parent-theme-css', get_template_directory_uri() . '/style.css');
   }
   add_action('wp_enqueue_scripts', 'child_theme_css');
endif; // child_theme_css

I recommend this method, which I find to be more elegant.

If you want to override other files in a parent theme all you need to do is copy files under the same directory structure to the child theme.

For example, to override parts/header/variant-1.php file you need to create the parts/header/ path within the child theme and copy the variant-1.php file.

Parent theme requirements

To be able to create child themes, the parent theme should be written properly. It is important for parent theme to use following:

function_exists for all the functions in functions.php file

The functions.php file is unique, this is the only file which is always loaded from both a base theme and a child theme. The file from the child theme is loaded firstly, directly before the file from the parent theme. Thanks to this it is possible to overwrite only selected functions from the parent theme. However, it is possible only when all the functions in functions.php file will use function_exists function. Without this a problem with duplication of functions definitions would appear.

It is recommended to follow this pattern:

if(!function_exists('theme_slug_fn_name')) :
   function theme_slug_fn_name() {
      // ...
   }
endif; // theme_slug_fn_name

get_template part

Second important function is get_template_part function, which can be used to create reusable theme sections for child themes.

Using this function is really easy:

get_template_part('slug', 'name');

In this situation WordPress will try to load following files:

  1. slug-name.php from child theme
  2. slug-name.php from parent theme
  3. slug.php from child theme
  4. slug.php from parent theme.

Attention! If none of the above exists, WP won’t raise any errors.

Plugins overriding

When you use more complicated plugins, you can override them in a theme too. Plugins like WooCommerce or BuddyPress have a template system, which is handy for easily overriding the plugin’s code from a theme. That’s why sometimes you would create a child theme only to add/modify the support for a given plugin.

If a plugin hasn’t got the template system built-in, all you can do is rely on the author’s predefined actions and filters.

Thing to keep in mind

If you want use child theme, it is worth to compare your modified files with files which were updated in the parent theme. Sometimes, your overrides can lead to problems with compatibility.

You should rely on common sense when using child themes - if you end up overriding most of the files, child themes are not that useful - you still need to take care of code incompatibilities in many places. Personally, I’d recommend creating your own theme with a similar appearance - it is a more optimal solution and will save you a lot of hassle in the future.

Summary

There is no perfect solution that would allow you to always override themes safely. Solutions offered by WordPress are satisfactory but they still have some drawbacks.

There is always the risk of certain incompatibilities between the overridden and updated code appearing. That being said, the proposed solutions allow us to save time during each and every update but above all - allow us to finish the update process in the first place, saving us from a myriad of problems.