Personally, I have never used a custom header image like those included in the TwentyTen and TwentyEleven themes. I think that they look great on other people’s sites, just not my own. Now, when you’re theming for the masses, you can pretty much toss all of your personal preferences out the window. In my opinion, a good theme should be as flexible as possible. If WordPress provides an easy-to-implement solution, it’s usually a good idea to implement it! I recently came up with a neat solution to a design problem involving custom header images.
The Problem
The theme should look good with or without the header image. Now, I’ve pretty much fleshed out the design of my theme at this point and I really like how it looks without a header image. The design needs to be modified if this is going to work at all.
The most logical place to put the header would be where the site title, tagline and primary navigation menu are currently displayed. If I inject the image directly above this information the image looks great, but this pushes the site title down by 200 pixels and I really do not like this! Another idea would be to inject the image directly below the primary navigation menu. This doesn’t really look as nice in my opinion. The image seems to look best when it is at the top of my content div. What to do? I have some cake. I want to “eat it too”. I just hope that the cake is not a lie!
The solution that I decided on involves a little bit of logic that will move the title and tagline to the top of the screen if a header image has been defined by the user.
Digging Into Some Code
Here’s a simplified version of a cross-section of my header.php file before I got started. This code demonstrates how the theme should work when no header image is defined. (Only the relevant parts of the template are included.)
<div id="wrap"> <div id="page"> <?php print '<div id="site-title">' . esc_html( get_bloginfo( 'blogname' ) ) . '</div>'; print '<div id="tagline">' . esc_html( get_bloginfo( 'description' ) ) . '</div>'; wp_nav_menu(); ?>
To add a header image that looks acceptable to me, I would need to adjust the code to look like this:
<div id="wrap"> <?php print '<div id="site-title">' . esc_html( get_bloginfo( 'blogname' ) ) . '</div>'; print '<div id="tagline">' . esc_html( get_bloginfo( 'description' ) ) . '</div>'; wp_nav_menu(); ?> <div id="page"> <?php printf( '<div id="header-image"><img src="%1$s" width="%2$s" height="%3$s" alt="%4$s"></div>', esc_url( get_header_image() ), esc_attr( HEADER_IMAGE_WIDTH ), esc_attr( HEADER_IMAGE_HEIGHT ), esc_attr( get_bloginfo( 'blogname' ) ) ); ?>
Notice that all of the code inside the #page division has been moved outside and replaced by code to generate a header image.
Technically, I have two unique versions of header.php at this point which needs to be dealt with. But what to do? Initially, I thought that I could add an option to allow user to choose the header template to use. I could even make one of those fancy template selectors like I’ve seen in Genesis and the Options Framework. Depending on which template the user chose, I could load a different version of header.php. Maybe I could create a custom header-image.php to help facilitate this.
Whenever I get the idea of adding an option to a theme, I really take a look at the situation and ask myself if it is really necessary to do so. Most of the time I am able to talk myself out of it. This shown itself to be one of those times.
Two Templates Bad. One Template Good.
I decided that adding a bit of logic to one header.php would probably be a better solution. Here’s a breakdown:
Get some info
To make a decision we will need to know if the user has defined a header image. This is very easy to do. We will use WordPress core function get_header_image(). This function will return a url to the header image if one has been set. If not, it will return an empty string. The first step is to store this the return value of this function in a variable.
<div id="wrap"> <?php $header_image = get_header_image(); ?>
The next step is to determine whether the site title, tagline and primary navigation menu should be printed outside of the page division. We decided above that this should only happen if a header image has been defined by the user. We can easily test for a non-empty value:
<div id="wrap">
<?php
$header_image = get_header_image();
if ( ! empty( $header_image ) ) {
print '<div id="site-title">' . esc_html( get_bloginfo( 'blogname' ) ) . '</div>';
print '<div id="tagline">' . esc_html( get_bloginfo( 'description' ) ) . '</div>';
wp_nav_menu();
}
?>
We’ll need to add a second conditional statement inside the page div as well. If the user has defined a header image we want to print the code to display that image. If not, we will need to print site title, tagline and primary navigation menu as they will not be printed above the page division when no header image has been defined by the user.
<div id="page" class="contain" role="document">
<?php
if ( ! empty( $header_image ) ) {
printf(
'<div id="header-image"><img src="%1$s" width="%2$s" height="%3$s" alt="%4$s"></div>',
esc_url( get_header_image() ),
esc_attr( HEADER_IMAGE_WIDTH ),
esc_attr( HEADER_IMAGE_HEIGHT ),
esc_attr( get_bloginfo( 'blogname' ) )
);
}
else {
print '<div id="site-title">' . esc_html( get_bloginfo( 'blogname' ) ) . '</div>';
print '<div id="tagline">' . esc_html( get_bloginfo( 'description' ) ) . '</div>';
wp_nav_menu( apply_filters( 'nighthawk_menu_args_primary' );
}
?>
Duplicate Code
The logic works really well and provides the result that I was after, but unfortunately we have now duplicated the code the print the site title, tagline and navigation menu. The following code appears twice:
print '<div id="site-title">' . esc_html( get_bloginfo( 'blogname' ) ) . '</div>'; print '<div id="tagline">' . esc_html( get_bloginfo( 'description' ) ) . '</div>'; wp_nav_menu();
Now, you may be thinking: “Come on Mike, it’s only three lines. What’s the big deal?”. Well, the actual code that I’m curreny using in the theme is much longer and looks a bit like this:
if ( 0 != (int) get_theme_mod( 'nighthawk_display_site_title', 1 ) ) {
$text = get_bloginfo( 'blogname' );
if ( ! empty( $text ) ) {
if ( ! is_front_page() || is_paged() ) {
$text = '<a href="' . esc_url( home_url() ) . '">' . esc_html( $text ) . '</a>';
}
print "\n" . '<div id="site-title">' . $text . '</div>';
}
}
if ( 0 != (int) get_theme_mod( 'nighthawk_display_tagline', 1 ) ) {
$text = get_bloginfo( 'description' );
if ( ! empty( $text ) ) {
print "\n" . '<div id="tagline">' . esc_html( $text ) . '</div>';
}
}
wp_nav_menu( apply_filters( 'nighthawk_menu_args_primary', array(
'container' => 'div',
'container_id' => 'menu-top',
'menu_class' => 'menu',
'theme_location' => 'primary',
'depth' => 1,
'items_wrap' => '<ul id="%1$s" class="%2$s" role="navigation">%3$s</ul>',
'fallback_cb' => '_nighthawk_menu_dialog',
) ) );
It’s about 8 times as long. I really hate repeating myself when writing code, so I needed a solution to deal with this. The first thought I usually have is to bundle it into a function and then call the function twice. This solves the problem of repeated code, but introduces another issue. It’s a PITA to work around. This theme is going to be released to the public and one thing that I know for sure is that people will want to customize it. putting this code inside a function and hiding it away in functions.php is pretty easy to do, but if your users are not comfortable editing php files, chances are they are going to edit php files!
WordPress 3.0 introduced a function called get_template_part() which is a perfect alternative to creating theme functions. In my situation, it is the perfect solution. I moved the code above into a new file which I named top.php and then, in header.php, I included this new file with get_template_part(). My header.php now looks a bit like this:
<div id="wrap">
<?php
$header_image = get_header_image();
if ( ! empty( $header_image ) ) {
get_template_part( 'top', 'with-image' );
}
?>
<div id="page" class="contain" role="document">
<?php
if ( empty( $header_image ) ) {
get_template_part( 'top', 'no-image' );
}
else {
printf(
'<div id="header-image"><img src="%1$s" width="%2$s" height="%3$s" alt="%4$s"></div>',
esc_url( $header_image ),
esc_attr( HEADER_IMAGE_WIDTH ),
esc_attr( HEADER_IMAGE_HEIGHT ),
esc_attr( get_bloginfo( 'blogname' ) )
);
}
?>
Now, my header works as I would like it to, the code is as clean as possible and no code has been duplicated. Good times!
Did You See What I Did There???
If you look closely at each instance of get_template_part() you’ll see that I am passing the optional second parameter which allows you to give content to the template. Since we are using the file in two different contexts – “with an image” and “without an image” – it made sense to do this. “Why?” you ask. Well, this will give the most control possible the the end user. After they install my theme, if they need to customize it, they can easily create a child theme so that the original theme can be updated. If they decide that they do not like the code I have provided in top.php, all they need to do is create their own top.php in their child theme and modify it as they see fit. But creating top.php will change the code that displays both inside and outside the page division. This may or may not be desirable. What if they only want to change the code that displays outside the page division? Since we added context to the template part, this is relatively easy to do. A user can create a file named top-with-image.php. This file will only be called outside of the page division and the theme will use the original top.php when this template is called inside the page division.
Questions? Concerns?
Hope you enjoyed this! I know I was pretty excited when I came up with this solution. If you have anything to add to the conversation, please do so in the comments section.



What I have always been very confused with is when to use
and
and tend to use the former more than the latter. One of these days, I will have to pick your brains for better understanding. :)
Very interesting and great way to solve it. I love template parts, there’s a lot of cool stuff to do with them.
I have a simple parent theme I use as base start for most of my client’s website. I recently found very helpful to have html-open ( from the Doctype to the end of the
</head>element ) and html-close ( onlywp_footer()and</html>) both as template parts called from header.php and footer.php files respectively. This allows me to keep those two important parts of the theme separate, giving me the possibility to update them via the parent theme at any time regardless of any change done to the header.php or footer.php files of the child theme. It also makes me feel better not having to duplicate all the html head code just to change a logo position or similar.