A few months ago I wrote an article about how to use CSS to create a nice looking map. The process was (I think) well explained in that article, and now I want to show you the real example — or how to use CSS and unordered list to create live, nice looking CSS map (that hopefully rocks :)

CSS map in practice

I personally love XHTML and CSS combination even when we should achieve the same effect with Flash. This is partly because I never explored Flash so much. The client of ours — Oxy Polyclinic wanted for us to create a map of diving locations for their Ship “Borna”. We could create a map by using Flash, but we used simple XHTML and CSS instead. Why?

Well, one of the reasons, and not a small one was that we wanted to have links that can be followed by search engines. If we used Flash, the links inside Flash movie couldn’t be followed. The other reason was that we wanted the map to be viewed by as many visitors that shouldn’t be bothered with installing Flash plug-in. We know that today most users have Flash installed, but then, if we don’t care about those who haven’t, why should we bother with any other browser except Firefox and Internet Explorer?

The code

The code is very simple. The two differences you will notice from the previous article are: we used CLASS selectors on list-items. We used classes because we had two different diving locations to show, and by using classes we could style them differently. The second change is that we added a text that will be hidden until we went over him with a mouse. Let’s start.


<div id="map">
<ul id="locations">
<li class="ship" id="ship1"><a href="#" title="Coreolanus"><span>Coreolanus</span></a></li>
<li class="dive" id="dive1"><a href="#" title="Banjol Island"><span>Banjol Island</span></a></li>
</ul>
</div>

CSS behind the code

We have one DIV that we use as a container for our map. This is here because on Diving Borna web site we used the CSS map functionality elsewhere, for example to show the ships layout. So, in this first DIV we define the width and height of it, and we load the background image.


#map {
	width:350px;
	height:400px;
	background:url(istra-map.gif) no-repeat;
}

Next, we should define the list itself. Naturally, we don’t want to display the bullets. Also, we positioned the list relatively. It is very important not to forget this, because we will position the links absolutely to it. We should also reset the margin and padding values. If you don’t do this, you will have problems in Internet Explorer (unless you solved it by applying some other reset method).


#locations {
	list-style:none;
	position:relative;
	margin:0;
	padding:0;
}

Next, we will style the links. Every location is represented by different image (sunken ship uses light green, and dive location uses light blue). Because we wanted to make as few HTTP requests as possible, we created one image that contains icons for all the states (sunken ship, dive location, hover and selected state and already visited). Every icon is 10x10px and because of that we gave our link the same width and height values. Because every location is in different position, the links will be positioned absolutely.


#locations a {
	width:10px;
	height:10px;
	display:block;
	position:absolute;
}

Now it’s time to style the different diving locations. Every diving location is different and we know which one it is by different classes. We have two of them (ship and dive). Depending on a class, the link is styled differently and the background image is moved accordingly.


#locations .dive a 	{ background:url(icons.gif) no-repeat 0 0 }
#locations .ship a 	{ background:url(icons.gif) no-repeat -20px 0 }

We used the same approach for :hover, .selected and :visited states. If the mouse is over a link or the link is selected (we are currently viewing the diving location) the background-image is moved -40px to the left. If the link is already visited the image is moved -60px.


#locations .ship a:hover,
#locations .dive a:hover,
#locations a.selected { background:url(icons.gif) no-repeat -40px 0 }
#locations a:visited { background:url(icons.gif) no-repeat -60px 0  }

After we styled the links, we have to style the text. Now, if you just want to use some kind of simple text or an image, you don’t have to use SPAN for displaying text (take a look at the past article). But I used SPAN so I can hide the text until we came across it with the mouse. The text is hidden with #locations a span { display:none }, and it pops-up when the mouse is over a link with #locations a:hover span { display:block }.

The rest of the code is pretty easy to understand. We positioned the text relatively to the link (which is, BTW, positioned absolutely) just in case we want it a bit removed from the link (like I did in this example). We also defined the size and weight of the font, color and line-height. We made a box around the text by defining the background color and width and height of the SPAN. Text is a bit removed from the borders with padding. The opacity is defined just to make a box transparent (at least under Firefox, it looks cool :). You could use the Alpha filter if you want to achieve the same effect under IE.


#locations a span {display:none; }

#locations a:hover span { 
	display:block;
	position:relative;
	top:-5px;
	left:15px;
	font-size:1.1em;
	font-weight:bold;
	color:#CCC;
	line-height:15px;
	width:150px;
	height:30px;
	padding:2px 5px;
	background:#333;
	opacity:.7;
} 

Now, what is left is to position the links to its positions. By observing the code you will see that we used both ID and CLASS selectors on list-items. The ID selector is used for positioning the link to its position. Since the ID selector should be used to identify one element (at least if you want to validate a page), we used ID for positioning since every location is unique. Here is the sample code for this.


#ship1 a { top:70px; left:5px }
#dive1 a { top:125px; left:20px }

It seems that we did everything we could, but in the testing process I discovered a strange bug that bothered me both on Firefox and IE.

CSS map in practice

Some diving locations were visible even when the mouse was over other location, and that just wasn’t very nice. I solved the problem by defining the z-index:1 for a and a.selected and z-index:1000 for a:hover.


#locations a, #locations a.selected { z-index:1 }
#locations a:hover { z-index:1000 }

Take a look at example and live version

Example
Live version @ DivingBorna.com

Please note: Since the live version went live a few months ago, I made some slight changes in this article. If you would like to use this kind of approach for creating CSS Maps, you should always consider this article instead of live version. Live version is here only to demonstrate the possibilities behind this kind of approach.


Comments

9 responses to “CSS map in practice”

  1. Great posting. I’ve just re-done a map for a client who had opened at a new location and this post has inspired me to create something which is more dynamic and easy to manage. Will let you know how it goes as going to start on it tomorrow!

    Thanks.

  2. I am glad this article helped you John and please share with us the final result :)

  3. @Nikola – Appreciated.

  4. Hey this is a really cool idea! If you haven’t seen it yet, check out Eric Meyer’s CSS bar graphs.

  5. Beth, CSS bar graphs is another good example on how CSS can be used in practice :)

  6. Kinda newbee to CSS and want to use Your map on my site. I’ve put the CSS in separate file and called it from HTML. I’ve changed the picture and the dim’s but in IE I got cutted bg image and the locations (positions) are all messed up and I can’t see them as well.
    Can You help?

    edit: može i na hrvatski, lol

  7. This is great! Excellent work. I have one question. In addition to the hovering over the dive locations, is there a way to use a list of links to activate the spans in there proper locations?

    Sort of like having two ways to view the locations…hovering over the icons AND a linked name of the location.

    Any help or a link to a similar solution would be helpful!

Leave a Reply

Your email address will not be published. Required fields are marked *