Building a Twenty Ten Child Theme

This article will describe the process I followed building the Twenty Ten Weaver (TTW) child theme. To simplify things, I’ve actually stripped down TTW into a smaller child theme called Twenty Ten Heads Up (TTHU) that only tweaks Twenty Ten’s header.

We aren’t going to cover the details of how a child theme works – that has been done already. Here’s the WordPress.org article on themes, and a corresponding article on child themes. And op111.net has another good child theme tutorial.

While some themes and child themes concentrate on adding features or specialized look and feel, TTW mostly fiddles with the parent’s CSS rules via an admin interface under WP’s Appearance menu in the main admin interface. Thus, this tutorial will concentrate more on building the admin interface than the features of the theme. We will be discussing the files contained in the twentyten-headsup folder.

At a minimum, a child theme could consist only of a new style.css file. The next most obvious file to include is a functions.php. In this example, the style.css file does nothing other than define the child theme and add the parent style.css. The functions.php file provides the hooks into the parent theme and the overall WP environment. One more file, mytheme-options.php defines most of the admin interface.

Adding CSS overrides and other features

We will discuss the admin part later. In this section, we will discuss some basic tools for overriding the parent’s CSS and hooking in other features. In general, there are four ways to override a parent theme’s behavior. The easiest is to generate CSS override rules, either in the style.css, or by inserting <style> blocks into the <head> section of the generated WP post or page.

The other two involve interacting with the parent’s own functions.php file. It is possible to redefine some of the functions within the parent functions.php (which this example does not do), or to define some filters to override behaviors (which this example uses to redefine the height of the header image).

Finally, if the parent theme just won’t let you do something you want, then you can provide replacement files in your child theme for some of the parent’s php files. TTW in fact provides replacements for four files: header.php (to allow the ability to better control the look of the header), footer.php (to allow insertion of content into the footer), and index.php and page.php to allow support of the new top and bottom widget areas. We won’t really discuss these features any more in this tutorial.

Overriding CSS in the <HEAD> section

So first, let’s look at overriding CSS. CSS rules are typically found in a .css file – usually called style.css for a WP Theme. One of the features of CSS is that it will use the most recently defined rule – so the HTML page can start with the default style.css, but then include more rules that override the originals. And the WordPress design has this feature built in for theme and filter writers. One adds a “hook” to WordPress using the add_action function. In this case, the action is called 'wp_head'. After WordPress has emitted what it needs to for the <HEAD> section of the page, right before it emits </HEAD> (these are standard parts of every HTML page), it will call any hooks that have been added using add_action. In TTHU’s functions.php file, this call is at the very end of the file: add_action('wp_head','mytheme_wp_head').

Now the function mytheme_wp_head really does the work of generating the CSS overrides. Depending on which options have been set in the admin panel (using the built in WP database functions update_option, get_option, and delete_option), the appropriate CSS override rules are emitted into a <style> section of the <HEAD> section. A look at the code in mytheme_wp_head should make it obvious how this is done.

<br />
function mytheme_wp_head() {<br />
/* mytheme_wp_head is called as a result of the add_action(&#8216;wp_head&#8217;, &#8216;mytheme_wp_head&#8217;)<br />
  call at the end of this  file. It is called the end of the main WP wp_head function, and is<br />
  really where almost all of the real work of this child theme gets done. Essentially,<br />
  this function outputs  overrides of the parent theme to  give the custom look as<br />
  defined by the options.<br />
 */<br />
    global $themename, $myThemeTrans, $options, $myThemeHeadOptions;	/* need these globals */</p>
<p>    /* here, we output our style sheet overrides. The first one loads parent theme stuff. */ ?&gt;<br />
	&lt;link href=&quot;/style.php&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;</p>
<p>    &lt;style type=&quot;text/css&quot;&gt;<br />
&lt;?php<br />
    /* so, depending on what options we&#8217;ve set from the admin panel, we will emit various bits of CSS in the output */</p>
<p>	$val = t_get_option_setting(&quot;myopts_after_header&quot;);       /* check if space changed */<br />
        if ($val != &#8221;) {<br />
            echo(&quot;#main { padding: $val&quot;); echo (&quot;px 0 0 0; }\n&quot;);<br />
        }<br />
	/* options to change the menu bar colors */<br />
	if (($optColor = t_get_opt_color(&quot;myopts_menubar_color&quot;)) != &#8221;) {<br />
		t_css_bgcolor(&#8216;#access&#8217;, $optColor);<br />
	}<br />
	if (t_get_option_setting(&quot;myopts_bold_menu&quot;)) {<br />
		echo(&quot;#access, #access li ul ul a {font-weight:bold;}&quot;);<br />
	}<br />
        /* and so on&#8230; The full file has more options, but we&#8217;ve taken them out here for brevity. */<br />
?&gt;<br />
    &lt;/style&gt; &lt;!&#8211; end of style section &#8211;&gt;<br />
&lt;?php<br />
 }<br />

Using filters

Another common way to do various things in WordPress is with filters. Whenever a piece of WordPress has something that might need to be changed by a plugin or theme, it often uses a filter. If the plugin, theme, or in this case, child-theme, wants to override some default value, it can install a filter. In this example, Twenty Ten uses a filter to generate the height of the header image (also the width, but we only change the height.)

The filter is added at the end of our functions.php file with this line:

add_filter('twentyten_header_image_height', 'childtheme_set_hi_height');

When the parent theme wants to generate a value for the header image height, it will pass the default value through a filter. And here’s the filter – again using a value set in the admin panel.

<br />
function childtheme_set_hi_height($def) {<br />
	global $themename, $options;<br />
	/* Filter to change the height of the default header image.<br />
	  This filter is called by the parent theme,<br />
	and is used to change the height of the header image. */</p>
<p>	$val = t_get_text_option_value(&quot;myopts_header_image_height&quot;);<br />
    	return (int) $val;<br />
}<br />

Building a Theme Admin Panel

We’ve now shown how to add simple CSS overrides to a generated HTML page, and how to use a filter to change some theme defaults. The next question is: How do we get all those option values set? The answer, of course, is with a theme admin panel in the Appearance menu of the main WP admin page.

Once again, the theme admin page is added through the theme functions.php file. It is sort of a two step process. First, you use add_action to add a function that will add a new admin menu. That function then defines what gets called when the new menu item is selected by the user.

So:

  1. Add new admin menu item:
    add_action('admin_menu', 'mytheme_add_admin');
  2. In mytheme_add_admin, define theme control page:
    $page = add_theme_page($themename, $themename, 'edit_themes', basename(__FILE__), 'mytheme_admin');
  3. Define the theme control page:
    function mytheme_admin() { ... }

The add_action is at the bottom of our functions.php. Here’s the mytheme_add_admin function:

<br />
function mytheme_add_admin() {<br />
    global $themename, $myThemeTrans;<br />
    /* this is invoked due to the add_action at the bottom of this file, and is what actually adds our<br />
      item to the main WP admin panel */</p>
<p>    $page = add_theme_page($themename, $themename, &#8216;edit_themes&#8217;, basename(__FILE__), &#8216;mytheme_admin&#8217;);</p>
<p>    /* Because our admin panel uses some javascript, using the registered $page handle, we hook the script loading<br />
    stuff, but just for this admin page */<br />
    add_action(&#8216;admin_print_styles-&#8217;.$page, &#8216;myopts_admin_scripts&#8217;);<br />
}<br />

And finally, the actual mytheme_admin code:

<br />
function mytheme_admin() {<br />
    /* theme admin page<br />
      This page is called when the user picks the Theme Admin from the admin page pane.<br />
      Any form buttons that are pressed get passed through here, so the first thing to do is to<br />
      scan the $_POST values to see if the user pressed any of your form buttons.<br />
    */</p>
<p>/* This puts out the startup script calls, etc, for the admin page */<br />
    global $themename, $myThemeTrans, $options;<br />
    global $theme_options;<br />
    $myopts_dir =	get_bloginfo(&#8216;stylesheet_directory&#8217;);<br />
?&gt;<br />
&lt;?php<br />
     /* First, process any actions from the buttons. This simple theme has only one button &#8211; save options. */</p>
<p>    if ($_POST['saveoptions']) {<br />
        echo &#8216;&lt;div id=&quot;message&quot; class=&quot;updated fade&quot;&gt;&lt;p&gt;&lt;strong&gt;&#8217;.__(&quot;Theme main options saved.&quot;,$myThemeTrans).&#8217;&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;&#8217;;</p>
<p>	foreach ($options as $value) {<br />
	    if( isset( $_POST[ $value['id'] ] ) ) {<br />
		update_option( $value['id'], $_POST[ $value['id'] ]  ); } else { delete_option( $value['id'] );<br />
	    }<br />
	}<br />
    }</p>
<p>   myopts_options_admin(); 	/* now display the options to the user &#8211; via a form */ ?&gt;</p>
<p>&lt;h3&gt;Preview of site &#8211; after you save options or select sub-theme.&lt;/h3&gt;<br />
&lt;iframe id=&quot;preview&quot; name=&quot;preview&quot; src=&quot;&lt;?php echo get_option(&#8216;siteurl&#8217;);  ?&gt;?temppreview=true&quot; style=&quot;width:100%;height:400px;border:1px solid #ccc&quot;&gt;&lt;/iframe&gt;</p>
<p>&lt;/div&gt;<br />
&lt;/div&gt;<br />
&lt;?php<br />
}<br />

Note that the theme_admin code shown here mostly does some housekeeping, and calls
myopts_options_admin to display the actual options form. One important task of theme_admin_code is to handle the actions generated by the form in the admin page -
in this case responding to the 'saveoptions' action, and picking up values from the $_POST array filled in by the form.

Design of the admin form

Generally, the goal of the form displayed by myopts_options_admin is to let the user set various values. This example has adopted a strategy of using the built in WordPress options database to store these values. You use get_option and its related functions update_option and delete_option to save the values for use in the code generating functions such as mytheme_wp_head. Our code also uses the array $options to define a list of options that can then be displayed using a loop. It is equally valid to define a form with more custom entry fields. Our theme also uses the jscolor Javascript to have the value fields for colors filled in with color and a color picker pop up.

A lot of this is simple form design, which is a bit beyond the scope of this article. The main points to remember are to use get_option, etc. to save and retrieve option values, then have the mytheme_wp_head function use those values to generate CSS overrides – for the most part. There are other ways to add functionality to the child theme.

Conclusion

We hope this covers the main points of building a simple child theme, including adding ad admin panel for the theme. The Twenty Ten Heads Up child theme is a greatly simplified version of Twenty Ten Weaver. After you get the main points of this smaller theme, you should be able to figure out what some of the other things TTW is doing as well.

Comments
Trackbacks