Using Images for Menus and Page Headings

Part of using CSS and xhtml for web design is a goal to keep all images that aren't content out of the content. To keep all those images that make a site design in the design. Sometimes this turns out not to be so easy. Two situations I've seen designers not follow this rule on is menus and page headings or titles. Let's dig into how to create image menus and headings without putting images or even html into your content.

I'll admit it. In the past I've put images in the content. This was partly because I was lazy and didn't want to dig into something new and partly because I didn't understand how to do it. Someone challenged me to figure out how to do it so I finally learned.

SiFR and Text to Images

These two methods are two to consider right up front. They work by automatically generating the image. If you are going to replace all of your blog titles, for example, with a special font not found in your browser these two methods should be considered. Though, they do have their shortcomings and don't fit every use case.

sIFR uses flash and javascript to replace the regions you tell it with the font you specify. If you don't have flash or javascript it gracefully degrades to the font you specify in your css. If you are using drupal check out the sIFR module.

The other method is to use something like the GD library in PHP to create your image. This is more processing intensive on every page load and I wouldn't recommend it for larger sites. It does have a greater capability than sIFR. If you can create it with an image editor you should be able to do it with GD. This is included in PHP but isn't the only image generation option. And, to create theme images may not be close to easy. If you are using drupal check out the textimage module for a start.

Replacing Text With Images

Now, let's look at how to do this on a case by case basis with CSS. Start by creating your menu or page title as you would text based. This will be important for mobile devices and screen readers. I'm going to show a page title as the concept is simpler here.

Make sure the xhtml you use allows you to have a unique identifier for the different elements. For a heading you might consider something like:

<div id="content-123">
  <h2>My Title</h2>

In this case the 123 could be your contents unique id. So, in your css you can uniquely get to that title via #content-123 h2. And, each heading you want to change would just be a few new lines in your css.

Note: In drupal nodes the standard id surrounding a div for a node is node-123 where 123 is the node id.

To replace that with an image the css would look something like:

#content-123 h2 {
  text-indent: -10000px;
  overflow: hidden;
  width: 150px;
  height: 20px;
  background-image: url(path/to/image.jpg);

The CSS here sets the height and width of the element to the width and height of the image. Setting the text-indent to a large negative number pulls text off the screen. Hidden overflow stops the text from overflowing anywhere.

If your a CSS nut you might think that this is not the best looking CSS. It isn't. This is the way that works for Internet Explorer. I tested several other methods, including setting the element height to 0 and putting the image in the padding, but they all failed to work in older versions of IE.

This method will effectively replace the content of the h2 with your image for just that instance. Search engines, mobile browsers, and screen readers will still see the text making this an accessible option as well.

When it comes to menus you have the complication of a mouse over image in many cases. For that situation have an a:hover element with a different background image and when you mouse over the image changes.

Autoloading All Those Images!

You might be thinking that your going have replace quite a number of page titles with images and you don't want them to all load on every page. That's part of the beauty of browsers. They don't load all of the images in your css. Just the ones they are going to use. This is the reason that background images in a:hover elements need to be preloaded to escape the delay of the browser loading them when you first mouse over a link.

By keeping these images in the presentation layer we can keep our layers of separation and the freedom of developers to develop.