Customize the Theme in Two Ways
While it could be easy to achieve what we want by editing the theme directly, it is also true that everytime the theme will be updated we’ll have to do all the customizations again. This can be frustrating, so there’s another option: we can create a child theme and use the >functions.php> file to modify the parent themefeatures. In this way we can upgrade the parent theme everytime a new version is released without losing our customizations.
Before we step into more specific details, a brief note about the theme appearance: we can modify colors, backgrounds, typography and the layout through the style.css file of the child theme by importing the parent style.css and overriding the styles we want to change.
For more control on the layout, we can also follow how Abbas Suterwala suggests in his post and clone the parent custom template files in our child theme:
Then the child theme could optionally override other template files like author.php, category.php, etc. The WordPress framework first looks for a template file in the child theme directory and then if not found will pick it up from the parent directory.
What We Can Modify
Through the child theme’s functions.php file we can deal with:
- Theme features
- Custom post types and taxonomies
- Menus and sidebars
- Widgets
- Shortcodes
- Additional image sizes
- Metaboxes
- JavaScript and CSS
- Parent theme actions and filters
So, let’s say we have this web site structure:
- htdocs OR www
- wp-content
- themes
- foo-theme (directory of the parent theme – it will not be modified)
- functions.php
- header.php
- style.css
- other template files…
- foo-theme-child (directory of our child theme)
- functions.php (the file we will use to customize the parent theme)
- header.php (overrides header.php for the parent theme)
- style.css (this is a required file in a child theme and must be namedstyle.css)
- foo-theme (directory of the parent theme – it will not be modified)
- themes
- wp-content
Let’s get started: create an empty functions.php file in the /wp-content/themes/foo-theme-child/directory.
For the most part we will use a generic wp_tuts_remove_features()
function, hooked to the WordPressafter_setup_theme
action. We also set 10
as a third parameter (priority), so we are sure that the function is triggered before the parent one.
add_action( 'after_setup_theme', 'remove_parent_theme_features', 10 ); function remove_parent_theme_features() { // our code here }
1. Remove Theme Features
Some parent themes add features to WordPress through the add_theme_support
function.
Available features are:
post-formats
post-thumbnails
custom-background
custom-header
automatic-feed-links
So to remove them, we can modify the remove_parent_theme_features()
function in the functions.phpfile.
function remove_parent_theme_features() { remove_theme_support( 'post-formats' ); remove_theme_support( 'post-thumbnails' ); remove_theme_support( 'custom-background' ); remove_theme_support( 'custom-header' ); remove_theme_support( 'automatic-feed-links' ); }
2. Remove Custom Post Types and Taxonomies
Removing custom post types and custom taxonomies is easy: if the parent functions.php file adds aMovie custom post type, through a parent_movie_add_post_type()
function:
// PARENT functions.php add_action( 'after_setup_theme', 'parent_movie_add_post_type' ); function parent_movie_add_post_type() { $parent_args = array( // other arguments... 'rewrite' => array( 'slug' => 'movie' ), 'supports' => array( 'title', 'editor', 'author', 'excerpt' ) ); register_post_type( 'movie', $parent_args ); }
… we can customize it thanks to our child functions.php file:
// CHILD functions.php function remove_parent_theme_features() { // remove Movie Custom Post Type remove_action( 'init', 'parent_movie_add_post_type' ); /* alternatively, we can add our custom post type to overwrite only some aspects of the parent function */ add_action( 'init', 'child_movie_post_type' ); } function child_movie_post_type() { $child_args = array( // other arguments... // change Custom Post slug 'rewrite' => array( 'slug' => 'child-movie' ), // remove excerpts and add post thumbs 'supports' => array( 'title', 'editor', 'author', 'thumbnail' ) ); register_post_type( 'movie', $child_args ); }
We can also remove only certain features without unregistering the post type, for example if we want to replace the excerpt field with a post featured image, we can modify the function in this way:
function remove_parent_theme_features() { add_action( 'init', 'wp_tuts_remove_post_feature' ); } function wp_tuts_remove_post_feature() { // remove excerpt remove_post_type_support( 'movie', 'excerpt' ); // add post thumbs add_post_type_support( 'movie', 'thumbnail' ); }
You can find a complete list of removable features under remove_post_type_support
in the WordPress Codex.
Similar to custom post types, you can remove a custom taxonomy added in the parent theme by aparent_taxonomy()
function, in this way:
function wp_tuts_after_setup_theme() { remove_action( 'init', 'parent_taxonomy' ); }
3. Remove Menus
We can remove a parent theme’s menu through the unregister_nav_menu()
function. This function takes one parameter, the menu location identifier slug used in the register_nav_menu()
function.
If the parent theme registers a Header Menu:
// PARENT functions.php add_action( 'after_setup_theme', 'register_my_menu' ); function register_my_menu() { register_nav_menu( 'header-menu', __( 'Header Menu' ) ); }
We can remove it in this way:
// CHILD functions.php function remove_parent_theme_features() { unregister_nav_menu( 'header-menu' ); }
To identify registered menus, we can search the parent theme code for register_nav_menu()
calls. The first argument of the function represents the menu ID we can use to unregister (in this case header-menu
).
4. Remove Widgets and Sidebars
WordPress comes with some default Widgets that we can deactivate. Also, our parent theme could add its own widgets, so we can search in the theme files looking for where they are declared and take note of their name. Usually they are declared in a PHP class that extends the WP_Widget
class:
// PARENT theme class ParentWidgetName extends WP_Widget { // widget code }
So, to unregister the widget, we use the class name ParentWidgetName
:
add_action( 'widgets_init', 'wp_tuts_parent_unregister_widgets', 10 ); function wp_tuts_parent_unregister_widgets() { // remove (some) WordPress default Widgets unregister_widget( 'WP_Widget_Pages' ); unregister_widget( 'WP_Widget_Calendar' ); // remove Parent registered Widget unregister_widget( 'ParentWidgetName' ); // register a custom Widget (if needed) register_widget( 'MyCustomWidget' ); } // don't forget to add the Widget Class class MyCustomWidget extends WP_Widget { // Custom Widget code }
For sidebars the action is similar:
add_action( 'widgets_init', 'wp_tuts_parent_unregister_sidebars', 10 ); function wp_tuts_parent_unregister_sidebars() { // remove a sidebar registered by the Parent Theme unregister_sidebar( 'first-footer-widget-area' ); }
To identify registered sidebars, we can search the parent theme’s code for register_sidebar()
calls.
All we need is to take note of the sidebar ID:
// PARENT functions.php $args = array( 'id' => 'first-footer-widget-area', // other args... ); register_sidebar( $args );
5. Remove Shortcodes
Overriding or removing shortcodes is easy, we only need to modify our function in this way:
function remove_parent_theme_features() { // remove the parent [gmap] shortcode remove_shortcode( 'gmap' ); // add our [gmap] shortcode add_shortcode( 'gmap', 'child_shortcode_gmap' ); } function child_shortcode_gmap( $atts ) { // create our shortcode that overwrites the parent one }
To identify registered shortcodes, we can search the parent theme code for add_shortcode()
calls. The first parameter is the one we’re after ;-).
6. Remove Additional Image Sizes
If the parent theme adds new image sizes that we don’t use in our child theme, we can search the parent theme code for add_image_size()
calls. In this case they are: custom_size_parent_1
andcustom_size_parent_2
. We reset them in this way:
add_filter( 'intermediate_image_sizes_advanced', 'remove_parent_image_sizes' ); function remove_parent_image_sizes( $sizes ) { unset( $sizes['custom_size_parent_1'] ); unset( $sizes['custom_size_parent_2'] ); return $sizes; }
This is useful because every time the user uploads an image, WordPress will not create additional image sizes that we don’t use.
To create custom image sizes we can add this in our child functions.php file:
if ( function_exists( 'add_image_size' ) ) { // 400 pixels wide and unlimited height add_image_size( 'custom_size_child_1', 400, 9999 ); // 320 pixels wide and 240 px tall, cropped add_image_size( 'custom_size_child_2', 320, 240, true ); }
7. Remove Metaboxes
Through the remove_meta_box()
function we can remove both default WordPress and parent theme metaboxes.
A list of WordPress default metaboxes is available under remove_meta_box()
in the WordPress Codex. The function has three arguments: the metabox ID, the page it will be removed from, the editing context (normal
, advanced
, side
).
If the parent theme adds metaboxes in the post editing screen, we can disable them in this way:
add_action( 'admin_menu' , 'wp_tuts_remove_metaboxes', 99 ); function wp_tuts_remove_metaboxes() { // remove default WP Trackback Metabox from Posts editing page remove_meta_box( 'trackbacksdiv', 'post', 'normal' ); // remove a Parent Theme Metabox 'parent_post_foo_metabox' remove_meta_box( 'parent_post_foo_metabox', 'post', 'normal' ); }
We can identify parent metaboxes by searching the parent theme code for add_meta_box
oradd_meta_boxes()
calls.
The ID of the metabox to remove is the first argument of the add_meta_box()
function.
8. Remove JavaScripts and CSS Stylesheets
If the parent theme adds JavaScript and CSS styles that we don’t need:
// PARENT functions.php add_action( 'wp_print_scripts', 'parent_scripts' ); add_action( 'wp_print_styles', 'parent_styles' ); function parent_scripts() { wp_enqueue_script( 'fancybox-parent-js', get_stylesheet_directory_uri() . '/fancybox/jquery.fancybox.pack.js' ); } function parent_styles() { wp_enqueue_style( 'fancybox-parent-css', get_stylesheet_directory_uri() . '/fancybox/jquery.fancybox.css' ); }
We can remove them in this way:
// CHILD functions.php add_action( 'wp_print_scripts', 'child_overwrite_scripts', 100 ); add_action( 'wp_print_styles', 'child_overwrite_styles', 100 ); function child_overwrite_scripts() { wp_deregister_script( 'fancybox-parent-js' ); } function child_overwrite_styles() { wp_deregister_style( 'fancybox-parent-css' ); }
To identify registered JavaScripts and CSS styles, we can search the parent theme code forwp_enqueue_script()
and wp_enqueue_style()
calls.
The first argument of the function is what we can use in the wp_deregister_script()
orwp_deregister_style()
functions.
9. Remove Parent Theme Actions and Filters
Some themes, like Thematic provide several hooks to modify the theme behavior without altering the theme files. In this case, Thematic provides a thematic_header
action that loads other actions:
thematic_brandingopen()
thematic_blogtitle()
thematic_blogdescription()
thematic_brandingclose()
thematic_access()
We will not examine in detail what these functions do, probably some of them print some info in the blog header: name, description, and so on… In this case we can deactivate the thematic_blogdescription()
function in this way:
// Unhook default Thematic functions function unhook_thematic_functions() { // we put the position number of the original function (5) // for priority reasons remove_action( 'thematic_header', 'thematic_blogdescription', 5 ); } add_action( 'init', 'unhook_thematic_functions' );
In these cases it can be hard to understand the structure of the parent theme and how it works. My advice is to choose a parent theme that ships with detailed documentation, a good support forum, and makes hooks available throughout the code.
This surely makes us lose less developement time and make the customization of the child theme easier.
References
- Child Themes Basics and Creating Child Themes in WordPress
- WordPress Codex Documentation
after_setup_theme
remove_action
add_theme_support
register_post_type
add_post_type_support
remove_post_type_support
register_nav_menu
unregister_nav_menu
register_widget
unregister_widget
register_sidebar
unregister_sidebar
add_shortcode
remove_shortcode
add_image_size
add_meta_box
remove_meta_box
wp_deregister_script
wp_deregister_style
- A collection of WordPress Parent Themes