Backwards compatibility for WordPress 3.4 headers and backgrounds

As I mentioned in the previous post, the new versions of WordPress custom headers and backgrounds have some great new features, but they require WordPress 3.4. That’s no problem if you’re already steering your custom development towards 3.4 (and you should be), but if you’re building themes for distribution, you can’t be sure that all your users are going to upgrade on the first day or even month.

Michael Fields, Automattic Theme Wrangler and all-around smart theme guy, pointed me toward the latest version of P2, which has a rather nice way of handling the backwards compatibility issue for just this case: (This function is called within theme setup)

function p2_setup_custom_header() {
	$args = array(
		'width'               => 980,
		'height'              => 120,
		'default-image'       => '',
		'default-text-color'  => '3478e3',
		'wp-head-callback'    => 'p2_header_style',
		'admin-head-callback' => 'p2_admin_header_style',
	);

	$args = apply_filters( 'p2_custom_header_args', $args );

	if ( function_exists( 'get_custom_header' ) ) {
		add_theme_support( 'custom-header', $args );
	} else {
		// Compat: Versions of WordPress prior to 3.4.
		define( 'HEADER_TEXTCOLOR',    $args['default-text-color'] );
		define( 'HEADER_IMAGE',        $args['default-image'] );
		define( 'HEADER_IMAGE_WIDTH',  $args['width'] );
		define( 'HEADER_IMAGE_HEIGHT', $args['height'] );
		add_custom_image_header( $args['wp-head-callback'], $args['admin-head-callback'] );
	}
}

Elsewhere in the theme setup function, P2 also uses:

	$args = apply_filters( 'p2_custom_background_args', array( 'default-color' => 'f1f1f1' ) );
	if ( function_exists( 'get_custom_header' ) ) {
		add_theme_support( 'custom-background', $args );
	} else {
		// Compat: Versions of WordPress prior to 3.4.
		define( 'BACKGROUND_COLOR', $args['default-color'] );
		add_custom_background();
	}

That’s taken direct from P2 — you’ll have to make adjustments for your own themes: change the slugs, set up the options you want to use, etc.

I can’t think of any reason you couldn’t wrap both function_exists() checks into one conditional, but I’m inclined to keep them separate — it’s easier to read, easier to override in child themes, and if one extra check is a performance concern, it’s time to add a second hamster to your hamster wheel…

(On the other hand, I’m not a fan of holding on to backward compatibility beyond a couple of core versions back. There are a lot of themes out there still checking if widgets are supported, and at that point it’s just cruft. Be nice to your code.)

Flexible headers in WordPress 3.4 themes

As of WordPress 3.4 Beta1, theme authors can allow custom header images with flexible heights, widths, or both.

In other words, instead of being limited to a fixed size determined by the designer, as you’re already familiar with:

With flexible headers, you can allow users to upload smaller or larger headers without having to make a child theme or (worse) hack your theme, like so:

How to do it:

Image header support in 3.4 no longer uses all the constants that had to be defined in previous versions — HEADER_IMAGE_HEIGHT, HEADER_IMAGE_WIDTH, HEADER_TEXT_COLOR and the like are now gone. Instead, all the header support options are included in a single array, and enabled with a call to add_theme_support() in your theme’s functions.php file.

This is how the array looks in the theme I used for the screenshots above:

// Add support for flexible headers
 $header_args = array(
 'flex-height' => true,
 'height' => 200,
 'flex-width' => true,
 'width' => 950,
 'default-image' => '%s/images/headers/path.jpg',
 'admin-head-callback' => 'mytheme_admin_header_style',
 );

 add_theme_support( 'custom-header', $header_args );

If flex-height or flex-width are not included in the array, height and width will be fixed sizes, replacing the old HEADER_IMAGE_HEIGHT and HEADER_IMAGE_WIDTH. If flex-height and flex-width are included, height and width will be used as suggested dimensions instead.

Don’t forget to remove any references to the old constants in your template files — in my header.php, I simply replaced.

<img src="<?php header_image(); ?>" width="<?php echo HEADER_IMAGE_WIDTH; ?>" height="<?php echo HEADER_IMAGE_HEIGHT; ?>" alt="" />

with:

<img src="<?php header_image(); ?>" height="<?php echo get_custom_header()->height; ?>" width="<?php echo get_custom_header()->width; ?>" alt="" />

For reference, here’s the full set of options and their default values, as found in /wp-includes/theme.php. Note that the other header image options like text, text color, and randomization are available in the same add_theme_support() call by setting only the options you need:

$defaults = array(
'default-image' => '',
'random-default' => false,
'width' => 0,
'height' => 0,
'flex-height' => false,
'flex-width' => false,
'default-text-color' => '',
'header-text' => true,
'uploads' => true,
'wp-head-callback' => '',
'admin-head-callback' => '',
'admin-preview-callback' => '',
);

A few important notes:

  • Flexible header support has to be built into each theme – it will not work automatically with your pre-existing themes.
  • This functionality requires WordPress 3.4, which is currently in beta. You can grab the latest here (.zip file). Please use it for testing and development, but don’t run it in production unless you know what you’re doing and have some risk tolerance.
  • Design-wise, flexible heights are relatively easy; flexible widths are much trickier to work into a layout while still looking good. Experiment!