Buttons over images

by Joe Gillespie — Nov 1, 2004

If you want to put multiple links on an image, in a navbar or diagram for instance, the usual way to do it is with an imagemap.

I hate imagemaps!

Not only are they difficult to set-up and edit, they can cause accessibility and usability problems and belong in the trash can along with frames and blink tags. Where a 'normal' button can have a rollover effect that gives visual feedback, with an imagemap you are depending on a cursor change or lumbered with IE's ugly link outlines.

It's impractical to swap a large JPEG image to achieve a rollover effect. It's not a good idea to have text on a JPEG image anyway as the compression used doesn't work well for type. Having multiple rollover images is also a fairly complex process. Breaking images up into a multitude of smaller slices is one way to get round it but a single image will load faster and cleaner than one that is all sliced-up because there is only one request sent to the server and one download.

Ideally, we should have a static JPEG image for the main picture and then place small, bandwidth-friendly, link buttons on top of that image. Those button images can have transparent backgrounds, if you like, so that they blend in with the background image seamlessly. This gives the best of both worlds – efficient JPEG compression for the background image and crisp, clean type on the button – plus you have the benefit of having rollover effects that you can control.

Putting a button on top of an image is easy with CSS. If the image is the background of a relatively positioned CSS box (div), we can use absolute positioning to put small buttons anywhere we like on top of that image with pixel accuracy, achieving perfect image-on-image registration if necessary.

Navbar Example

Here is a typical imagemap navbar. As it's a photographic image, it is saved in .JPG format but because it contains type too, the compression has to be kept to around the 70% mark in Photoshop's 'Save for Web' or the type would exhibit nasty compression artefacts. So, the image file size is about 16K.

Each of the menu items is linked through an imagemap to another page (well, it would be in a real situation.)

stonehenge image map

The clues that the reader gets that these are actually links are fairly subtle. I'll list them...

  • The cursor changes to a pointing finger.
  • The status bar (if present) would show the URL of the linked page.
  • The context is a clue in this instance but it's not always the case.

Below, is a seemingly identical navbar but this time, I've used a box called #stonehenge which has the JPG image as its background. There is no type on the background image so I can compress it much more, in fact, this image is only 5.7K instead of 16K. The logo and link text are small foreground GIF images.

Now, when the mouse goes over the links, they emboss and when they are clicked, they deboss. These are tri-state buttons, each with a normal (off) state, a rollover state and a clicked state.

Their backgrounds are transparent and the 3D effects are produced by appropriately colored single pixel lines for highlights and shadows.

The links are separate, absolutely positioned buttons (#shb1...#shb4), so they can go anywhere inside the navbar. They are in a single straight line here, but they don't have to be. They can be in diagonal lines or curved sweeps – you have complete control.

A link <a href=...> can't be attached to a background image, so each button has a transparent GIF (clear8.gif) in the foreground.

Before CSS positioning came along, people used clear GIFs to fake positioning. The single pixel clear GIF still has its uses – except that single pixel GIFs are too small and fiddly and are easy to lose, so my clear GIFs are 8 x 8 pixels.

Interactive Images

Another way that imagemaps are often used is to provide more information about objects in a picture – a bit like heavy-duty tooltips. This is very useful in cataloges and diagrams.

Here is another background/foreground imagemap substitute. The food jars are the background image of a div called #foodshelf and over each jar is a button (#jar1...#jar8) with a clear GIF in it.

Instead of linking to pages, as is the case with a navbar, the buttons link to a JavaScript function that makes the 'about' text (#about1...#about8 divs) visible or not and also change the border style of the jar buttons from none to solid.

function showAbout(n) { var borderCol="#393"; if (document.getElementById) { for (i=1;i<=8;i++) { // first give all buttons invisible borders var ibutton = document.getElementById("jar"+i); ibutton.style.border="1px none " + borderCol; // and make sure the about text is hidden var about = document.getElementById("about"+i); about.style.visibility="hidden"; } // now, give the active button a green border colour var ibutton = document.getElementById("jar"+n); ibutton.style.border="1px solid " + borderCol; // and make the appropriate about box visible var aboutBox = document.getElementById("about"+n); aboutBox.style.visibility="visible"; } }

Tip: Although the button borders are initially invisible and only turn green on mouseover, if you temporarily make the initial borders 'solid', you can see them and adjust their margin-left, margin-top, width and height to register perfectly with the objects. When they are all in the right place, change the initial style back to 'none'.

The only small price to pay for not using imagemaps is that with div buttons, we can currently only have rectanglar hot spots. There are situations where you might have to use ovals or polygons. For those, you will have to stick with imagemaps for the minute.

Del.icio.us Digg Technorati Blinklist Furl reddit Design Float