How to add customizable header images and customizable backgrounds to your WordPress theme

One of the coolest new features of WordPress 3.0 is the ability to customize the site header image and background color or image. The custom header actually goes one step further and lets you set a unique header for each of your pages. This means that you can create unique headers that tie into the content of the page without complex if (is_page()) statements or hard coding them into unique page templates. The only problem is that these features need to be added into the theme for them to show up as options in your wp-admin panel and not every free (or even commercial) theme has those options set up and ready to go.

Not all themes are made for big, changeable headers, but for those that are or would adapt well, this gives users a powerful resource far beyond the custom header features that Kubrick, the previous default WordPress theme, offered with its’ ability to change the header color and gradient. Likewise, I’m tentative about giving users the ability to pick a color at random from the 16 million colors at their disposal – it’s too easy to create clashes worthy of the most gaudy GeoCities or MySpace creations. However, used with discretion and a keen eye, these features add a powerful tool to those WordPress users’ arsenal who are just itching to add a little bit of personality to their site without breaking everything.

Our newest free theme, Color Garden includes both custom headers and custom backgrounds, making it our first theme – free or otherwise – to offer both. I also played with custom headers on my recent redesign of jazzsequence.com. For the headers, it’s not the most intuitive thing to add by hand at all, and few of the resources I have found go far beyond quoting the code from TwentyTen’s functions.php file, so we wanted to give our readers just a little bit more to go on if you want to add these features to your blog theme.

Custom backgrounds are dead simple. A single line of code and you’re done:

// This theme allows users to set a custom background
add_custom_background();

Once this is included somewhere in your functions.php file, you will have a Background link under Appearance that gives you options to set a solid color for the background (by hex code or picking from a color map) or upload an file to use as a repeating background image.

Headers are a bit more complex.

To really understand how custom headers work, you need to know how post thumbnails work. Post thumbnails were added to WordPress core in 2.9 and use the built-in resizing process that happens when you upload images to create the thumbnails that will appear next to your post or post excerpt. This is presumably to replace other third-party scripts like the ubiquitous TimThumb which creates its own thumbnails and stores it in a cache folder usually located in the theme folder (although it could really be anywhere). Since WordPress 3.0, what was previously referred to as Post Thumbnail on the Add New Post page is now called Featured Image. This change is reflects the fact that the Featured Image option now controls the post thumbnail or the custom header, and the way it knows the difference is by the size of the image you are using.

Let’s take a look at how to add it to your theme and then we can revisit how to use it once it’s there. The code I will be showing comes from Color Garden although all of it has been adapted from TwentyTen (including much of the comments). Since most other posts I’ve found don’t discuss each piece of the header image function, I will go over each so you understand just what it is that you’re adding and what needs to be changed or left alone.

The first part is here:

// Your changeable header business starts here
// No CSS, just IMG call. The %s is a placeholder for the theme template directory URI.
define( 'HEADER_IMAGE', '%s/images/headers/leaves.jpg' );

The key thing to pay attention to in this snippet is the HEADER_IMAGE definition. This is the default header image. If this is left blank or set to an invalid path, no image will show up, and depending on your CSS, the layout might break. In TwentyTen this is set to %s/images/headers/path.jpg. You’ll probably want to put something here even if you plan on changing it later, and you’ll want to make sure the image actually exists where you say it exists.

The next part sets the height and width of your header image:

// The height and width of your custom header. You can hook into the theme's own filters to change these values.
// Add a filter to twentyten_header_image_width and twentyten_header_image_height to change these values.
define( 'HEADER_IMAGE_WIDTH', apply_filters( 'cg_header_image_width', 1000 ) );
define( 'HEADER_IMAGE_HEIGHT', apply_filters( 'cg_header_image_height', 343 ) );
 
// We'll be using post thumbnails for custom header images on posts and pages.
// We want them to be 1000 pixels wide by 343 pixels tall.
// Larger images will be auto-cropped to fit, smaller ones will be ignored. See header.php.
set_post_thumbnail_size( HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT, true );

Notice that we’re using set_post_thumbnail_size with the header image’s dimensions. This is because the custom header function uses the existing post thumbnails function from 2.9 and builds onto it. As the comments indicate, images that are equal to or larger than the height and width definitions will be resized to fit and set as the header image when you add it to your post or page. Anything smaller will be ignored and set as the post thumbnail (if post thumbnails are enabled).

The last part of the custom header function is this:

// Don't support text inside the header image.
define( 'HEADER_TEXTCOLOR', '' );
define( 'NO_HEADER_TEXT', true );
// ... and thus ends the changeable header business.

The NO_HEADER_TEXT and HEADER_TEXTCOLOR add the ability to change the color of the text that appears in the header. The alternative (pulled from the WordPress Codex) would be to use:

define('HEADER_TEXTCOLOR', 'ffffff');

and omitting the NO_HEADER_TEXT line.

Now this part is done, you’ve enabled custom headers and defined a default. But what if you want to have multiple defaults like TwentyTen? In that case, we go back to TwentyTen’s functions and keep digging:

// Default custom headers packaged with the theme. %s is a placeholder for the theme template directory URI.
register_default_headers( array(
 
'leaves' => array(
'url' => '%s/images/headers/leaves.jpg',
'thumbnail_url' => '%s/images/headers/leaves-thumbnail.jpg',
/* translators: header image description */
'description' => __( 'Leaves', 'cg' )
),
 
'sunset' => array(
'url' => '%s/images/headers/sunset.jpg',
'thumbnail_url' => '%s/images/headers/sunset-thumbnail.jpg',
/* translators: header image description */
'description' => __( 'Sunset', 'cg' )
),
 
'beach' => array(
'url' => '%s/images/headers/beach.jpg',
'thumbnail_url' => '%s/images/headers/beach-thumbnail.jpg',
/* translators: header image description */
'description' => __( 'Beach', 'cg' )
),
 
'blueberries' => array(
'url' => '%s/images/headers/blueberries.jpg',
'thumbnail_url' => '%s/images/headers/blueberries-thumbnail.jpg',
/* translators: header image description */
'description' => __( 'Blueberries', 'cg' )
)
) );

Again, we’re looking at the code from Color Garden but it’s adapted from TwentyTen’s functions.php. Each item in the array above defines one of the default header image options. Color Garden has four default headers to choose from to go with the four color schemes built into the theme. All we’re really doing here is adding the path to the image, the path to the thumbnail of the image that appears on the Headers page in the WordPress backend, and the description which – as far as I have been able to tell – really only affects the alt text of the image in the backend.

All said, what you should be looking at in your functions.php file when you’re done is this (if you’re including multiple default header images):

// Your changeable header business starts here
// No CSS, just IMG call. The %s is a placeholder for the theme template directory URI.
define( 'HEADER_IMAGE', '%s/images/headers/leaves.jpg' );
 
// The height and width of your custom header. You can hook into the theme's own filters to change these values.
// Add a filter to twentyten_header_image_width and twentyten_header_image_height to change these values.
define( 'HEADER_IMAGE_WIDTH', apply_filters( 'cg_header_image_width', 1000 ) );
define( 'HEADER_IMAGE_HEIGHT', apply_filters( 'cg_header_image_height', 343 ) );
 
// We'll be using post thumbnails for custom header images on posts and pages.
// We want them to be 1000 pixels wide by 343 pixels tall.
// Larger images will be auto-cropped to fit, smaller ones will be ignored. See header.php.
set_post_thumbnail_size( HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT, true );
 
// Don't support text inside the header image.
define( 'HEADER_TEXTCOLOR', '' );
define( 'NO_HEADER_TEXT', true );
 
// ... and thus ends the changeable header business.
 
// Default custom headers packaged with the theme. %s is a placeholder for the theme template directory URI.
register_default_headers( array(
 
'leaves' => array(
'url' => '%s/images/headers/leaves.jpg',
'thumbnail_url' => '%s/images/headers/leaves-thumbnail.jpg',
/* translators: header image description */
'description' => __( 'Leaves', 'cg' )
),
 
'sunset' => array(
'url' => '%s/images/headers/sunset.jpg',
'thumbnail_url' => '%s/images/headers/sunset-thumbnail.jpg',
/* translators: header image description */
'description' => __( 'Sunset', 'cg' )
),
 
'beach' => array(
'url' => '%s/images/headers/beach.jpg',
'thumbnail_url' => '%s/images/headers/beach-thumbnail.jpg',
/* translators: header image description */
'description' => __( 'Beach', 'cg' )
),
 
'blueberries' => array(
'url' => '%s/images/headers/blueberries.jpg',
'thumbnail_url' => '%s/images/headers/blueberries-thumbnail.jpg',
/* translators: header image description */
'description' => __( 'Blueberries', 'cg' )
)
) );

What I haven’t said yet is that in every instance that cg appears in the code, this specifically references Color Garden. In TwentyTen it’s twentyten. You can put whatever you want here so long as it remains internally consistent.

After you’ve got your functions.php set up, you still need to add in some code in your header.php to actually display the custom header image. What we have in Color Garden is taken almost verbatim out of TwentyTen.

	  <?php
          // Check if this is a post or page, if it has a thumbnail, and if it's a big one
          if ( is_singular() &&
                  has_post_thumbnail( $post->ID ) &&
                  ( /* $src, $width, $height */ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'post-thumbnail' ) ) &&
                  $image[1] >= HEADER_IMAGE_WIDTH ) :
              // Houston, we have a new header image!
              echo get_the_post_thumbnail( $post->ID, 'post-thumbnail' );
          else : ?>
              <img src="<?php header_image(); ?>" width="<?php echo HEADER_IMAGE_WIDTH; ?>" height="<?php echo HEADER_IMAGE_HEIGHT; ?>" alt="" class="masthead" />
          <?php endif; ?>

This is where the theme asks “what is the size of the featured image?” and, based on the size, determines whether it is a header image or a post thumbnail.

Now, obviously there needs to be some CSS styling involved and you may or may not want your header image to be 1000 pixels wide by 343 high like ours is in Color Garden. We added a “masthead” class to the image so we could isolate styles to our header image. But, if you’ve made it this far, you’ve got everything you need to tweak the code to suit your theme. The custom headers function is exciting because it doesn’t need to be limited to just header images. You can use it wherever you might want a customizable image in your theme, and there’s more than a few creative uses I can think of beyond headers for something like that.

You might also be interested in these:

  1. How I fixed the “cannot redeclare _checkactive_widgets()” error in WordPress child themes
  2. How to upgrade your Museum Theme to the most current version after you’ve made changes to the files
  3. 12 Free WordPress Themes I Like (and you should, too)