Drupal website specialists.

Image maps with CSS

Posted 19/July/2008 by neubreed

First we create an outer div which will be used to apply the background image. Our links will go inside a nested div to keep our code organised and allow us to apply styles to the links as a group. The nested div can also come in handy when using a style sheet switcher to create alternate CSS menu effects.

<div id="book">
 <div id="menu">
  ...
 </div>
</div>

The individual links can now be placed inside our nested div. Giving each link its own id allows us to independently position them on the page. These separate ids also act as anchors, letting users select the links directly no matter where they are located on the page, or their ability to click on them.

To make the text within each link invisible, we need to add another nested tag. I prefer to use semantically meaningless &lt;i&gt; tags because they provide visual clues to their presence in the absence of a stylesheet, which makes them easier to work with. They're also very short, which helps with code efficiency. However, you could certainly use &lt;span&gt;, &lt;em&gt;, or some other tag if you'd like.

<div id="book"> 
 <div id="menu"> 
  <a href="index.html" id="home"><i>Home</i></a>
  <a href="preface.html" id="preface"><i>Preface</i></a>
  <a href="stories.html" id="stories"><i>Stories</i></a>
  <a href="galleries.html" id="gallery"><i>Galleries</i></a>
  <a href="forums.html" id="forum"><i>Forum</i></a>
  <a href="mementos.html" id="mementos"><i>Mementos</i></a>
  <a href="credits.html" id="credits"><i>Credits</i></a>
  <a href="indicia.html" id="indicia"><i>Indicia</i></a>
 </div>
</div>

This is the all the XHTML that we need. You can see the results in Example 1. We can now move on to creating the image map effect with our stylesheet.

[b]Guided by a master plan[/b]

In your CSS file add a background colour for the document body and set the margin and padding to 0. We're going to be using absolute positioning, and this will help with our calculations.

body {
  background-color: #000;
  margin: 0;
  padding: 0;
  }

The background for our image map is applied to the outer div. You should set an appropriate height and width to make sure it is fully displayed.

#book { 
  background-image: url(/d/imagemap/images/»
   bookpages.jpg);
  height: 595px;
  width: 750px;
  }

Any styles that apply to the majority of the links can be defined together. More specific CSS rules can then be used to alter the attributes of individual links as required. Use absolute positioning and include a default height, width, and top position for all of the links. This is a good time to make sure the underlines are removed as well.

#menu a {
  position: absolute;
  height: 38px;
  width: 88px;
  top: 31px; 
  text-decoration: none;
  }

To hide the text within links while retaining “clickability,” we use a CSS selector to identify the italicised text within the links contained in our nested div, and its visibility is set to hidden. It's important to include meaningful link text, even if it will be invisible to the majority of your users. This ensures that your site will be accessible for browsers that don't support CSS and users who are viewing it with an alternate stylesheet.

#menu a i { visibility: hidden; }

Once the general CSS is in place, we can position each link individually. To improve efficiency, links that share a common attribute such as left or top, can be defined together.

a#credits, a#indicia { top: 531px; }
a#home { left: 101px; }
a#preface { left: 221px; }
a#stories { left: 311px; }
a#gallery { left: 431px; }
a#forum { left: 526px; width: 61px; }
a#mementos { left: 591px; width: 98px; }
a#credits { left: 431px; }
a#indicia { left: 591px; }

When applied to the XHTML of our document, the menu links will now float independently above our background image. If we position them above areas of the image that look like links, we'll be all set. Placing your links correctly will usually take either careful calculation or a bit of trial and error.

CSS image maps can use the :hover pseudo element to define a separate style for for each link's rollover state. This allows us to float new images above the background whenever the user moves their mouse over one of the invisible link areas.

a#home:hover { background-image: url(/d/imagemap/images/homeglow.jpg); }
a#preface:hover { background-image: url(/d/imagemap/images/prefaceglow.jpg); }
a#stories:hover { background-image: url(/d/imagemap/images/storiesglow.jpg); }
a#gallery:hover { background-image: url(/d/imagemap/images/galleryglow.jpg); }
a#forum:hover { background-image: url(/d/imagemap/images/forumglow.jpg); }
a#mementos:hover { background-image: url(/d/imagemap/images/mementosglow.jpg); }
a#credits:hover { background-image: url(/d/imagemap/images/creditsglow.jpg); }
a#indicia:hover { background-image: url(/d/imagemap/images/indiciaglow.jpg); }

A bug in Internet Explorer that causes the roll-over images to refrain from disappearing as expected can be fixed by adding border: none to the :hover state of all the CSS image map links.

a#home:hover,
a#preface:hover, 
a#stories:hover, 
a#gallery:hover, 
a#forum:hover,   
a#mementos:hover, 
a#credits:hover, 
a#indicia:hover { border: none; } 

You can see the final results of our CSS image map in Example 2.

[b]Post mortem[/b]

Using large background images isn't bandwidth-friendly, but it can produce compelling designs and give high-bandwidth visitors a richer visual experience. Because CSS image maps use standards-based XHTML, we could use a style sheet switcher to offer a low-bandwidth, alternate view of the site.