Gazi's Den

CSS Image Maps Guide

Prelude

So first of all, this is a guide to making image maps compatible with CSS. You might or might not already know the HTML maps made using <map> and <area>. And like, those are great, but they don't play nicely with custom CSS.

Additionally, this guide assumes you already know some HTML and CSS. Not necessarily modern HTML and CSS, though, so if you learned HTML in, like, 2005, this guide should still hold up for you.

I'm also assuming you want to learn to do this by hand, and not just, say, generate it with an online tool. If this assumption is wrong, check out the HTML Map Creator (offsite), or open up your favorite search engine and look up some variation of “html css image map tool”.

“Okay, Gazi,” you might say. “If there's tools to do this automatically, why bother learning it?” For the sake of learning! Or, more honestly, for the sake of saying you know how to do this without external tools. I know I'm not the only stubborn weirdo out there that likes to make things unnecessarily harder on themself.

Still here? Awesome, let's get into it.

The Task

So what we want to do is take this image (thank you, AnnaliseArt!):

and make it so when you hover over certain parts of it, you get:

  • a tooltip saying what that part is
  • an indication that you're hovering over it.

This is the end result (try hovering over something in the image!):

“Why are they all rectangles” shhh SHHH SHshshhshshsSHhshhh. Anyway.

The Tutorial

The first thing you need to know about this is, you're not using an <img> tag. Forget about the <img> tag, it doesn't exist to you right now. We're using a <div>.

“Why a div?” 'Cuz <img>s are block elements, and <div>s are block elements, so they have the same flow in a document. I guess if you wanted to be annoying (and go against semantic standards) you could modify a <span> or even a <p> and make that work for you, but we're trying to do things as well as possible here.

Step 1

<style>
    #map {
        background-image: url(https://gazimon.neocities.org/assets/img/park-annaliseart-pixabay.png);
        background-repeat: no-repeat;
        background-size: contain;
        height: 395.5px;
        width: 640px;
        position: relative;
    }
</style>

<div id="map" aria-description="A cheerful illustration of a park, including a climbing cage, a slide, a gazebo, a fountain, benches, a swingset, a fence, some trees, some flowers, and some flowering bushes.">
</div>

gets you the plain map above.

Breakdown

  • background-image: url(...): Since we're using a <div> element, to make it show up as an image, we need it to have a background image.
  • background-repeat: no-repeat: We only want one copy of the image to show up.
  • background-size: contain;: This constrains the image to the size of the <div>.
  • height/width: The size constraints. Without this, you won't see any image at all.
  • position: relative: This keeps the anchors from floating away all over your page. I'll explain the anchors later.
  • aria-description="...": We can't use alt="" for <div>s, so to keep things relatively accessible we'll use aria-description instead.

Cool, so this is a lot of code for a lot of nothing, huh? Yeah, just wait. We're gonna add our first anchor, just watch.

Step 2

<style>
    #map {
        background-image: url(https://gazimon.neocities.org/assets/img/park-annaliseart-pixabay.png);
        background-repeat: no-repeat;
        background-size: contain;
        height: 395.5px;
        width: 640px;
        position: relative;
    }

    .area {
        position: absolute;
        border: 2px solid black;
    }

    #climbing-cage {
        height: 75px;
        width: 72px;
        top: 85px;
        left: 97px;
    }
</style>

<div id="map" aria-description="A cheerful illustration of a park, including a climbing cage, a slide, a gazebo, a fountain, benches, a swingset, a fence, some trees, some flowers, and some flowering bushes.">
    <a id="climbing-cage" class="area" href="#" alt="A climbing cage." title="A climbing cage!"></a>
</div>

Boom! You can hover over the climbing cage now.

“Gazi,” you say, “Gazi, this is ugly.”

Calm down, we're getting there.

Breakdown

  • .area: Since we can't use <area> like in normal, non-CSS HTML image maps, we're making our own little class for it.
  • position: absolute: This is the reason our #map has a relative position. We need the anchors to be positioned using top and left (or bottom and right), so we need it to have an absolute position.
  • border: ...: The border is just for demonstration purposes right now. So you can see the box.
  • #climbing-cage: Here we are, our first anchor! We want these to be IDs instead of classes because, presumably, there should only be one of each anchor per map (per page). You can use classes though if you want. I'm not your dad.
  • height/width: The size of our anchor's/area's rectangle.
  • top/left: ...: The position of the anchor: 85px from the top, 97px from the left. You figure this out by the extremely scientific method of eyeballing it.
  • href="#": Normally, image maps are used for navigation, so this should probably be an actual link. But this isn't a guide for “how to link to other pages”, so we're not going to worry about that.
  • alt: Alt works for anchors! But not <div>s. Don't know why!
  • title: This is just our tooltip.

Step 3

But, yeah, it's ugly, and not much happens when we hover. This sucks. Let's change the hover behavior.

<style>
    #map {
        background-image: url(https://gazimon.neocities.org/assets/img/park-annaliseart-pixabay.png);
        background-repeat: no-repeat;
        background-size: contain;
        height: 395.5px;
        width: 640px;
        position: relative;
    }

    .area {
        position: absolute;
    }

    .area:hover {
        border: 2px solid yellow;
        background-color: rgba(255,255,0,25%);
    }

    #climbing-cage {
        height: 75px;
        width: 72px;
        top: 85px;
        left: 97px;
    }
</style>

<div id="map" aria-description="A cheerful illustration of a park, including a climbing cage, a slide, a gazebo, a fountain, benches, a swingset, a fence, some trees, some flowers, and some flowering bushes.">
    <a id="climbing-cage" class="area" href="#" alt="A climbing cage." title="A climbing cage!"></a>
</div>

Yeah, that's much better.

Breakdown

  • .area:hover: :hover is a CSS pseudo-class that lets you define the behavior of whatever you're hovering over. In this case, it's an anchor.
  • background-color: rgba(...): Went with the rgba() function so we could easily change the opacity of the background. Otherwise, we'd just have a fully opaque yellow rectangle show up when we hovered, which wouldn't be very helpful.

So now that we know how to do one anchor, the rest comes easy.

<style>
    #map {
        background-image: url(https://gazimon.neocities.org/assets/img/park-annaliseart-pixabay.png);
        background-repeat: no-repeat;
        background-size: contain;
        height: 395.5px;
        width: 640px;
        position: relative;
    }

    .area {
        position: absolute;
    }

    .area:hover {
        border: 2px solid yellow;
        background-color: rgba(255,255,0,25%);
    }

    #climbing-cage {
        height: 75px;
        width: 72px;
        top: 85px;
        left: 97px;
    }

    #slide {
        height: 88px;
        width: 120px;
        top: 74px;
        left: 242px;
    }

    #gazebo {
        height: 140px;
        width: 180px;
        top: 30px;
        left: 400px;
    }

    #fountain {
        height: 80px;
        width: 142px;
        top: 150px;
        left: 117px;
    }

    #swings {
        height: 80px;
        width: 135px;
        top: 245px;
        left: 45px;
    }

    #benches {
        height: 100px;
        width: 63px;
        top: 185px;
        left: 535px;
    }
</style>

<div id="map" aria-description="A cheerful illustration of a park, including a climbing cage, a slide, a gazebo, a fountain, benches, swings, a fence, some trees, some flowers, and some flowering bushes.">
    <a id="climbing-cage" id="area" href="#" alt="A climbing cage." title="A climbing cage!"></a>
    <a id="slide" id="area" href="#" alt="A slide." title="A slide!"></a>
    <a id="gazebo" id="area" href="#" alt="A gazebo with three visible stools and a table." title="A gazebo!"></a>
    <a id="fountain" id="area" href="#" alt="A fountain spraying water." title="A fountain!"></a>
    <a id="swings" id="area" href="#" alt="A swingset with two swings." title="Some swings!"></a>
    <a id="benches" id="area" href="#" alt="Two wooden benches." title="A couple of benches!"></a>
</div>

Ta-da! You did it! You coded an image map! \o/

If you really wanted to, and you were better at CSS styling than me, you could probably get the hover shapes to match the objects more precisely. But if not, I think the rectangles work just fine.


Questions? Feedback? I don't have anything set up for that yet, but feel free to comment on my site's profile and I'll see what I can do.