TUTORIAL

Creating an Image Map using CSS only

Introduction

An image map is a way of defining multiple clickable link areas (hotspots) within one image. These 'hotspots' can then used for navigation or to display information about the image they cover.

With this article I hope to show how you can turn an ordinary Definition List like this into an Image Map like this using nothing more than CSS, and what is more, it should work in all modern browser including Internet Explorer 5.5.

I will work through the styling a step at a time, fully explaining the reason for each style and showing the results of each step, so that you can see what to expect thus allowing you to follow the principles more easily.

Method

The following steps will describe how to add images to the definition list and style the text so that it only shows when specific areas of the main image are selected.

Step 1

My example Definition List starts out as a list of Beatles names (they come from my era so it seems a suitable choice), their instruments and a piece of trivia information. The (x)html is written as follows.

<dl>
 <dt>
  The Beatles
 </dt>
 <dd>
  Paul McCartney - Bass Guitar and Vocals
  <br />
  <br />
  Paul McCartney's song, Yesterday, recently 
  voted the most popular song of the century 
  by a BBC poll, was initially composed without 
  lyrics. Paul used the working title 'scrambled eggs' 
  before coming up with the final words.
 </dd>
 <dd>
  Ringo Starr - Drums
  <br />
  <br />
  Dear Prudence was written by John and Paul 
  about Mia Farrow's sister, Prudence, when 
  she wouldn't come out and play with Mia and 
  the Beatles at a religious retreat in India.
 </dd>
 <dd>
  John Lennon - Guitar and Vocals
  <br />
  <br />
  In 1962, The Beatles won the Mersyside Newspaper's 
  biggest band in Liverpool contest principally 
  because they called in posing as different people 
  and voted for themselves numerous times.
 </dd>
 <dd>
  George Harrison - Lead Guitar and Vocals
  <br />
  <br />
  The Beatles' last public concert was held in 
  San Francisco's Candlestick Park on August 29, 1966.
 </dd>
</dl>

Because there are four Beatles I will need to define four 'hotspots' but you can have as many as you like, the principle is the same.

In order that we can style this list we need to add information that will enable us to target specific elements.

<dl id="imap">
 <dt>
  <a id="title" href="#nogo" title="The Beatles">
   The Beatles
  </a>
 </dt>
 <dd id="picp">
  <a id="paul" title="Paul McCartney" href="#nogo">
   <span>
    Paul McCartney - Bass Guitar and Vocals
    <br />
    <br />
    Paul McCartney's song, Yesterday, recently 
    voted the most popular song of the century 
    by a BBC poll, was initially composed without 
    lyrics. Paul used the working title 'scrambled eggs' 
    before coming up with the final words.
   </span>
  </a>
 </dd>
 <dd id="picr">
  <a id="ringo" title="Ringo Starr" href="#nogo">
   <span>
    Ringo Starr - Drums
    <br />
    <br />
    Dear Prudence was written by John and Paul
    about Mia Farrow's sister, Prudence, when 
    she wouldn't come out and play with Mia and 
    the Beatles at a religious retreat in India.
   </span>
  </a>
 </dd>
 <dd id="picj">
  <a id="john" title="John Lennon" href="#nogo">
   <span>
    John Lennon - Guitar and Vocals
    <br />
    <br />
    In 1962, The Beatles won the Mersyside Newspaper's 
    biggest band in Liverpool contest principally 
    because they called in posing as different people 
    and voted for themselves numerous times.
   </span>
  </a>
 </dd>
 <dd id="picg">
  <a id="george" title="George Harrison" href="#nogo">
   <span>
    George Harrison - Lead Guitar and Vocals
    <br />
    <br />
    The Beatles' last public concert was held in 
    San Francisco's Candlestick Park on August 29, 1966.
   </span>
  </a>
 </dd>
</dl>

I have added the following style information to the (x)html.

  1. id="imap" - to the dl tag so that we can define it's size to hold the main image.
  2. <a id="title" href="#nogo" title="The Beatles"> ... </a> - Because Internet Explorer will only accept the :hover pseudo class on links, we need to surround the dt text with this link and give it an id="title". I have used href="#nogo" instead of the usual href="#" so that anyone clicking the link will not jump to the top of the page (just make sure you do not have an anchor #nogo on your page). The title="The Beatles" has been added so that it will appear when the mouse is hovered over the main image.
  3. Each dd has been given a unique id so that we can style each one.
  4. Each dd text has been surrounded by a link for the same reason as (2) above. These links have a unique id so that they can be individually targeted and a title as (2) above.
  5. Each dd text has also been enclosed in a span so that we can manipulate the text separately from the link.
This additional style information will change the definition list so that it looks like a list of links:-

Styled (x)html list

Step 2

Now that we have the definition list in a suitable format, I will take you through the various stages of styling

Firstly and most importantly, make sure that you have the correct (X)HTML !DOCTYPE. Without this most browsers will be thrown into 'quirks' mode which will lead to all sorts of incompatibility problems. W3C QA - List of valid DTDs has a list of valid DOCTYPES that can be used. Select from XHTML1.0 or XHTML1.1 as these are more suitable for this styling. I use XHTML1.1 for all my current web pages.

Step 3

The images

You will need to find or make a suitable main graphic for the Image Map. I have chosen a photograph of the Beatles that was available from the public domain. This image is 400px wide and 240px high.

The Beatles

Step 4

The <body> is first to be styled with the font-family for the whole page. I have chosen Tahoma as the first choice but you can select any font you wish.

<dl id="imap"> is next. This needs to be styled as a block with width and height values the same size as your main image. Your main image is then placed as a background image with no-repeat (so that we only get one) and finally a we give this a relative position so that we can place the four <dd>s using absolute positioning.

/* set up the font to be used for the page */
body {
  font-family: tahoma; arial, sans-serif;
  }

/* set the size of the definition list <dl> and add the background image */
#imap {
  display:block; 
  width:400px; 
  height:240px; 
  background:url(../images/beatles_basic.jpg) no-repeat; 
  position:relative;
  }
The results can be seen here:-

Example #1

You should see the main image with the text overlayed.

Step 5

Setting up the main image hover

Now that we have the main image in place we can set up the image that will indicate the active link areas. This image will be displayed when we hover over the main image.

In my example we will need four 'hotspots' and I have added these to the main image as shown below using an opaque area 85px square with a white border. For the sake of simplicity I have defined all the 'hotspots' as the same size. These could also have been rectangles of varying sizes.

It does not matter if the areas intersect each other as this will be taken care of in the styling.

The Beatles

Because the main image is held as a background image in the <dl> tag we need to place the hover image as a background image in the next tag available which will accept the pseudo class :hover style. This will be the link <a id="title" href="#nogo" title="The Beatles">

So we style this link as below:

/* set up the definition list <dt><a> to hold the background image for the hover state */
#imap a#title {
  display:block; 
  width:400px; 
  height:0; 
  padding-top:240px; 
  overflow:hidden; 
  position:absolute; 
  left:0; 
  top:0; 
  background:transparent url(../images/beatles_hover.jpg) no-repeat 400px 400px; 
  cursor:default;
  }
/* the hack for IE pre IE6 */
* html #imap a#title {
  height:240px;
  he\ight:0;
  }

Again we style this as a block with the same size as the hover image, but this time we use a height of 0px, a top padding of 240px and overflow hidden to move the text associated with the link out of sight. The hover image is set up as the background image and is also moved out of sight by giving it a position larger than the image size. The background color is transparent because we need the main image to show through.

I have also added a hack for Internet Explorer pre IE6 which corrects the box model bug.

With this style added there is no noticeable change to the page but to view this click on the link below:

Example #2

Step 5

The actual main image :hover

Now that we have the main image for the hover state in place it is a simple matter to style this to show when the mouse is placed over the image.

/* the <dt><a> hover style to move the background image to position 0 0 */
#imap a#title:hover {
  background-position: 0 0; 
  z-index:10;
  }

This moves the background image back into view at position 0 0. The z-index is added to ensure that the four 'hotspots' are always positioned above the hover background image (they will have a z-index of 20).

Example #3

You will see from the above example that we now have a change of image when hovered and also the title 'The Beatles' is also displayed next to the mouse.

Step 6

Placing the 'hotspots'

The position of each 'hotspot' is next to be styled. This requires the use of a paint package (or a little trial and error) the paint package method being easier. What we need to know is the x/y positions of the top left corners of each 'hotspot'.

This information is then used to style the four <dd>s as follows;

/* place the <dd>s in the correct absolute position */
#imap dd {
  position:absolute; 
  padding:0; 
  margin:0;
  }
#imap #picp {
  left:36px; 
  top:46px; 
  z-index:20;
  }
#imap #picr {
  left:113px; 
  top:76px; 
  z-index:20;
  }
#imap #picj {
  left:192px; 
  top:50px; 
  z-index:20;
  }
#imap #picg {
  left:262px; 
  top:60px; 
  z-index:20;
  }

We set up the position absolute in a common #imap dd style, then style each unique dd with a top and left position and a z-index of 20 to make sure that they are situated on top of the background image(s).

Example #4

Step 7

Styling the links

The next step is to style the links that have been placed in each <dd>.

/* style the <dd><a> links physical size and the background image for the hover */
#imap a#paul, #imap a#ringo, #imap a#john, #imap a#george {
  display:block; 
  width:85px; 
  height:85px; 
  background:transparent url(../images/hover.gif) -100px -100px no-repeat; 
  text-decoration:none; 
  z-index:20;
  }

Because all my 'hotspots' are the same size, I can group the style together. If you have 'hotspots' of varying sizes then you will need to style each one separately.

Each link is styled as a block 85px square with a background image that will be used when hovering over the 'hotspot'. Normally this image will not be displayed. The z-index is set at 20 to ensure that the links are always on top of the background image(s).

My link hover image is just a transparent gif with a white border, but you can use whatever you like.

Hover image

The above image shows the hover image over a blue background.

There is no noticeable change in the appearance of the page because we have not yet defined the :hover style for each link

Example #5

Step 8

Removing the span text

All the previous examples show the definition list text above the images. However, this text should only be displayed when we hover over a 'hotspot'. We will style the <span> text as below to hide it from view.

/* style the span text so that it is not initially displayed */
#imap a span, #imap a:visited span {
  display:none;
  }

Now things are starting to take shape:

Example #6

Step 9

Adding style to the 'hotspot' :hover

This is a simple matter of moving the link background image into view when we hover over each 'hotspot' and is achieved as below:

/* move the link background image to position 0 0 when hovered */
#imap a#paul:hover, #imap a#ringo:hover, #imap a#john:hover, #imap a#george:hover {
  background-position:0 0;
  }

As with the background hover, this is done by repositioning the background image at 0 0.

Example #7

Now when you hover the mouse over each 'hotspot' two things happen.

  1. You lose the background hover image and it reverts back to its normal unhovered image.
  2. The link hover image surrounds the selected 'hotspot' giving a dynamic change to the 'hotspot'.

Step 10

Displaying the span text

We now need to make the selected 'hotspot' text visible.

/* define the common styling for the span text */
#imap a:hover span {
  position:absolute;  
  width:388px; 
  display:block; 
  font-family:arial; 
  font-size:12px; 
  background:#fff; 
  color:#000; 
  border:1px solid #000; 
  padding:5px;
  }
/* the hack for IE pre IE6 */
* html #imap a:hover span {
  width:400px; w\idth:388px;
  }

In my example I have decided that the text should appear in a bordered block, the same width as our main image, with a white background. You can of course style this as you like.

I have again added the hack for Internet Explorer pre IE6.

Example #8

The first thing you will notice about the above example is that the text box is positioned with it's top left corner in the same positon as the top left corner of the 'hotspot' selected.

Step 11

Repositioning the span text

Because I want the text block to appear in the same position below the main image I need to recalculate the top left position of each span relative to the top left position of each 'hotspot'.

Doing this produces the following unique styling for each span text.

/* move the span text to a common position at the bottom of the image map */
#imap a#paul:hover span {
  left:-36px; 
  top:200px;
  }
#imap a#ringo:hover span {
  left:-113px; top:170px;
  }
#imap a#john:hover span {
  left:-193px; 
  top:196px;
  }
#imap a#george:hover span {
  left:-263px; 
  top:186px;
  }

Example #9

The above example should show that each text block now appears below the main image with the top left corner of each block having the same position. The blocks can vary in height as we have not fixed this value.

Step 12

A final bit of text styling

It is possible to further style the span text and I have chosen to do this using the following style. You can obviously style this as you wish.

/* add the style for the link span text - first line */
#imap a span:first-line {
  font-weight:bold; 
  font-style:italic;
  }

With this final piece of styling, which will display the first line of our text in bold italics, we end up with our completed Image Map.

Example #10

Conclusion

This tutorial shows just one of the ways in which Image Maps may be styled using just CSS. As long as you stick to the basic principles you can restyle this in literally hundreds of different ways. It is all down to you imagination and ingenuity, and of course your ability to use your favorite 'paint' software.