First time visitor? The tutorials start here.

Making Accessible Image Maps with CSS

You may have seen these around the web, images with various clickable areas that will take you to a different page, or to a different section of a page. To see how this was done in the past, see w3schools.com‘s tutorial on the <map> tag. For an example of the end result, click on the “Try it Yourself” button near the top of that page, then hover over the sun and planets in the sample.

There are some major drawbacks to using that method:

Already know the drawbacks? Skip the explanation and go straight to the solution.

  • It makes it necessary to use a mouse to navigate those links, thus making it inaccessible to the blind who rely on speech synthesizers and navigation via their keyboard.
  • It adds unnecessary (X)HTML to the page, which makes your pages:
    • bulkier,
    • less likely to be indexed completely by search engines,
    • more draining on your site’s bandwidth.
  • Some people like to disable graphics in browsers, while there are some non-graphical browsers like Lynx that don’t show images at all (that site isn’t perfect, but gives you a rough idea of what Lynx users will see if they visit this site). With the <map> method, people who can’t see the image won’t know where the links are in order to click on them.
  • (X)HTML on a page should make sense and describe the function of each element… <h#> tags for headings, <p> tags for paragraphs, <ul> or <ol> and <li> tags for lists, etc. Old-school image maps using the <map> tag are not conducive to this.

The method I show you here is more updated and addresses all of these issues.

Start with the (X)HTML

When designing a website, you should always, always, always start with the (X)HTML. As I mentioned above and in other places throughout this site, the tags you use should always describe the function of each element, without worrying so much about how they will look. Once you have the (X)HTML worked out, only then should you worry about visual appearance, and visual appearance should always be taken care of through CSS.

As a good rule of thumb, I always like to imagine how someone will see a site if it had no styling, or how a blind person would hear the site through a speech synthesizer. This is easy for you to do if you bookmark the following link and use it to view your pages: Disable Stylesheets. If you click on that link right now, you’ll see how this page looks without the CSS. To see the styling again, just refresh the page.

Let’s work with the w3schools example and make an image of our solar system lead to pages about the sun and various planets.

<ul>
    <li><a href="sun.htm">The Sun</a></li>
    <li><a href="mercury.htm">Mercury</a></li>
    <li><a href="venus.htm">Venus</a></li>
    <li><a href="earth.htm">Earth</a></li>
    <li><a href="mars.htm">Mars</a></li>
    <li><a href="jupiter.htm">Jupiter</a></li>
    <li><a href="saturn.htm">Saturn</a></li>
    <li><a href="uranus.htm">Uranus</a></li>
    <li><a href="neptune.htm">Neptune</a></li>
    <li><a href="pluto.htm">Pluto</a></li>
    <li><a href="ceres.htm">Ceres</a></li>
    <li><a href="2003ub313.htm">2003 UB<sub>313</sub></a></li>
</ul>

Before styling with CSS, the result would look something like the following sample. Note: If you use the code that is posted above, the links would go to different pages. But, since those pages don’t exist on this site, I made the links lead nowhere in the sample below.

If you are looking at the page through a non-graphical browser, or hearing it through a speech synthesizer, this would make sense and be easy to navigate. This, of course, is the desired result.

Turning that list into an image map with pure CSS

Now, we need to add IDs for everything, so we can use CSS to (1) add the image as a background for the whole list, as well as (2) position each link and hide the text:

<ul id="solar-system">
    <li><a id="sun" href="sun.htm">The sun</a></li>
    <li><a id="mercury" href="mercury.htm">Mercury</a></li>
    <li><a id="venus" href="venus.htm">Venus</a></li>
    <li><a id="earth" href="earth.htm">Earth</a></li>
    <li><a id="mars" href="mars.htm">Mars</a></li>
    <li><a id="jupiter" href="jupiter.htm">Jupiter</a></li>
    <li><a id="saturn" href="saturn.htm">Saturn</a></li>
    <li><a id="uranus" href="uranus.htm">Uranus</a></li>
    <li><a id="neptune" href="neptune.htm">Neptune</a></li>
    <li><a id="pluto" href="pluto.htm">Pluto</a></li>
    <li><a id="ceres" href="ceres.htm">Ceres</a></li>
    <li><a id="ub313" href="2003ub313.htm">2003 UB<sub>313</sub></a></li>
</ul>

Let’s use this image, which I obtained from this NASA page, which they obtained from the International Astronomical Union.

First, we need to:

  • Add the image as a background to the entire list,
  • Define the dimensions of the image map, which will be the same width and height as those of the image,
  • Use relative positioning on the list itself, because we’ll be absolutely positioning the links inside that area.

Using the id we gave to the <ul> tag, “solar-system,” the CSS would look something like this:

#solar-system {
	width: 800px;
	height: 450px;
	background:url(planets_iau.jpg);
	position: relative;
}

For this, I’m pretending the image is in the same directory as the page it’s being shown on, but you would change this url to reflect the actual directory and filename of the image. See: Absolute, Relative, and Root-relative URLs on how to do this.

Change the behavior of the list

<ul> and <li> tags come with margins and padding by default. To make sure these tags don’t create any layout problems, it’s good to remove these margins and padding, and also get rid of the bullets for good measure.

#solar-system, #solar-system li {
	margin: 0;
	padding: 0;
	list-style: none;
}

You’ll want to make it so people can click on any part of the sun and each planet for each link, otherwise they may have trouble finding the clickable part… especially when it comes to that huge sun. Anchor links are naturally inline elements, and you can’t define width or height on an inline element. Therefore, we need to turn those links into block-level elements. Since you are doing this to every link in that list, you can target them via the ul’s id, rather than defining each link via its own id.

Also, since every link will be absolutely positioned within the ul, you can define this along with defining them as block-level elements.

Finally, you’ll be wanting to hide the text for all the links, so you can add that here as well. To do this, use a negative text-indent to move the text off the left side of the screen. The exact amount is arbitrary, but it needs to be far enough to the left so it can’t be seen, regardless of what screen resolution it’s being viewed in.

To target every anchor link inside the ul, we use the id of the <ul>, followed by an a to target all <a> tags that are inside that particular list.

#solar-system a {
	display: block;
	position: absolute;
	text-indent: -100000px;
}

Just so you can see what area each link covers after they’re defined, let’s add a border to the hover state of our links. You can always take it back out later.

#solar-system a:hover {
	border: 1px solid #fff;
}

This post has multiple pages. Go to page: 1 2

If you found this article useful, please spread the word:
Stumble it! Digg! Tweet it!



Questions or comments?

Please log in to post a comment. Sorry, but it prevents this from happening. If you're not registered yet, you can register here.