Hierarchical Sitemap with Dashed Lines

This tutorial will use a nested unordered list with two levels to create a hierarchical structure where dashed lines will show the dependencies. This could be used as a sitemap or to visualize a directory. The advantage of this technique is that you only need a simple nested list and do not have to add any additional code in the HTML document.

Have a look at the final result.

Required knowledge: XHTML, CSS, How to create a transparent GIF (or use the ones provided).

Tested in: Firefox Internet Explorer 6 Internet Explorer 7 and 8 Netscape 8 Opera 8 Safari

I was looking for a way to represent the hierarchical structure of the portal of the Virtual Linguistics Campus. There will be some discussion about whether the simulation of a directory structure for this purpose is a good way to do so. But you should know that most users of this web site are rather unexperienced in using a computer and are always thankful to see elements that they recognize instantly. Thus, I decided to do exactly that.

The XHTML code

To start with, we are going to write the XHTML code for the unordered nested list, all valid strict XHTML 1.0 code (not to worry, it’s what you probably know anyway):

<ul id="sitemap">
	<li>Home</li>
	<li>Information
	<ul>
		<li>Personal</li>
		<li>Company Info</li>
	</ul></li>
	<li>Tutorials
	<ul>
		<li>Photoshop</li>
		<li>XHTML</li>
		<li>CSS
		<ul>
			<li>Explorer-like Sitemap</li>
			<li>Simple Horizontal Menu</li>
		</ul></li>
		<li>PHP</li>
	</ul></li>
	<li>Contact</li>
	<li>Links</li>
</ul>

This is pretty straight forward I guess.

Let’s start thinking about the CSS for the directory look. As you may know, we can use the style list-style-image to use any image we like instead of the usual bullets. For our purpose we could create an image with a vertical line running down infront of all list items and a horizontal line guiding the way to each item. Let’s try this with a simple list like the following:

<ul id="sitemap">
	<li>Home</li>
	<li>Information</li>
	<li>Tutorials</li>
	<li>Contact</li>
	<li>Links</li>
</ul>

The CSS for the lines and everything would look like this:

#sitemap {     /*leave this out if you've defined the font*/
	font-family: Verdana, Arial, Helvetica, sans-serif;
	font-size: 9pt;
	color: #000000;
}

#sitemap li {
	list-style-image: url(line_01.gif);
}

As always in web development, there is a problem…

At least I haven’t found a way to work around this phenomenon. If you use an image of a line which should continuously connect to the next line, forget about it what you will get is this (at least it looks the same in IE and Firefox😉 ):

2 Pixel Gap

The 2 pixel gap in Firefox 2 and Internet Explorer 7

I call this the gap problem and if you are Eric Meyer and you are reading this, maybe you could drop me a line and tell me how to avoid it (never mind that the rest of the tutorial may be too complicated anyway…). No matter what you do, set every margin and padding to 0, the gap will not disappear. You can of course make the font smaller but not until 5pt will you get a smaller gap between items. I also tried 1pt and there was still a gap between some items. Not all, which makes you wonder once again…

Now, you will say that the problem can be solved by defining the line-height style and you are right… Well, guess what: It only works for Firefox. Good ol‘ IE will misbehave again. Or was it Firefox that misbehaves? I’m getting tired of this. Fact is that no matter how you use line-height (number value, length value, or percentage value) both browsers present different results and I will not start thinking about other browsers yet. It would have been so nice… That’s why I left out the line-height altogether.

This is an appeal to the public: If you know a way to make this gap disappear (there is a doh!-solution I am sure) please send an e-mail. Thank you. As I said, there is a doh!-solution to the gap problem, see the end of the page for further info.

My work-around solution for the gap is to utilize it and create a dashed line which keeps in mind the two pixels in between list items. You could of course do it with a dotted line but not with every dotted line, you need to leave two pixels space in between and make sure that the top and bottom pixels are filled with color, just like the following screenshots exemplify:

Dashed Lines

Dashed

Dotted Lines

Dotted

Thus, we will use the gap to get a line which is continuous in some sense.

Now let’s try this on our nested list.

For a cool directory list, I want…

If you have a close look, we need a lot of different images to get a perfect look. Let’s make a list with things to avoid and things that we want:

  • The first level items (Home, Information, etc.) don’t need lines.
  • The lines start too close beneath the ‚mother‘ items.
  • The last item should be a corner and not continue into ’nothing‘.
  • Level three items need two lines to the left to continue the hierarchy structure.
  • Level four items… No, that’s something you can figure out for yourself. It’s late, this should suffice.

Let’s count. We need 8 different images for the nested list with three levels and here they are (I’ve added a border to make things less confusing):

Image for l2_normal Image for l2_first_followImage for l2_first_no_follow Image for l2_last_item Image for l3_normal Image for l3_first_follow Image for l3_first_no_follow Image for l3_last_item

Once we have them we can do everything else in CSS. Are you still with me? O.K. on we go.

The CSS part of the whole thing

Let’s think about how the structure of the nested list might help us to use as few classes as possible (maybe none at all). Have a look at the XHTML code again:

<ul id="sitemap">
	<li>Home</li>
	<li>Information
	<ul>
		<li>Personal</li>
		<li>Company Info</li>
	</ul></li>
	<li>Tutorials
	<ul>
		<li>Photoshop</li>
		<li>XHTML</li>
		<li>CSS
		<ul>
			<li>Explorer-like Sitemap</li>
			<li>Simple Horizontal Menu</li>
		</ul></li>
		<li>PHP</li>
	</ul></li>
	<li>Contact</li>
	<li>Links</li>
</ul>

Level 1 items are the children of the <ul> with the ID ’sitemap‘. We did not want any list style for them. So the CSS code for those list items is the following (let’s make it easy for a start, although this applies to all descendants of #sitemap):

#sitemap li {
	list-style-type: none;
}

Level 2 items are children of the unordered lists that are children of the aforementioned level 1 items (hey, they are grandchildren in other words…), so we could write this in order to get the first basic images:

#sitemap ul li {
	list-style-image: url(l2_normal.gif);
}

Level 3 items are children… and so on… You know how it works:

#sitemap ul ul li {
	list-style-image: url(l3_normal.gif);
}

You will see that we have some things to do. We need to change the image for the first entry on each level. We need to increase the margin between the level 1 items to make it all clearer. And we need to change the image for the last item.

To change the image for the first entry we need to introduce a class for level 2 and one for level three. The same applies for the last entry.

#sitemap ul li.firstfollow {
	list-style-image: url(l2_first_follow.gif);
}

#sitemap ul li.last {
	list-style-image: url(l2_last_item.gif);
}

#sitemap ul ul li.firstfollow {
	list-style-image: url(l3_first_follow.gif);
}

#sitemap ul ul li.last {
	list-style-image: url(l3_last_item.gif);
}

The changed XHTML code look like this:

<ul id="sitemap">
	<li>Home</li>
	<li>Information
	<ul>
		<li>Personal</li>
		<li>Company Info</li>
	</ul></li>
	<li>Tutorials
	<ul>
		<li>Photoshop</li>
		<li>XHTML</li>
		<li>CSS
		<ul>
			<li>Explorer-like Sitemap</li>
			<li>Simple Horizontal Menu</li>
		</ul></li>
		<li>PHP</li>
	</ul></li>
	<li>Contact</li>
	<li>Links</li>
</ul>

You may have seen the firstfollow class and asked yourselves, is there a firstnofollow class? Yes, because if there wasn’t we’d need only 6 images like in the list so far. I’ve added l[x]_first_no_follow.gif to cover the unlikely event that you only have one item.

I have also added a child selector in the stylesheet to increase the margin between level 1 items. This, however, does not work in IE because it does not support child selectors.

O.K., now the final stylesheet looks like this:

#sitemap {
	font-family: Verdana, Arial, Helvetica, sans-serif;
	font-size: 9pt;
	color: #000000;
}

#sitemap li {
	list-style-type: none;
}

ul#sitemap > li {
	margin-bottom: 10px;
}

#sitemap ul li {
	list-style-image: url(l2_normal.gif);
}

#sitemap ul ul li {
	list-style-image: url(l3_normal.gif);
}

#sitemap ul li.firstfollow {
	list-style-image: url(l2_first_follow.gif);
}

#sitemap ul li.last {
	list-style-image: url(l2_last_item.gif);
}

#sitemap ul ul li.firstfollow {
	list-style-image: url(l3_first_follow.gif);
}

#sitemap ul ul li.last {
	list-style-image: url(l3_last_item.gif);
}

Hope you like it and I’m looking forward to receiving your suggestions.

Questions/Problems/Disappointments

The only problem I can think of, is that users may adjust the font-size and this will break apart the whole structure. If you know that your users will not do this, you don’t have to bother. If you want it more flexible, you’ll have to think of whether this is the right thing for you, I’m afraid…

Suggestions from you, valued readers

27 March, 2006

Blair Miller suggested some easier code for almost the same effect. You might change the border style and the image (you only need one image in his example) to solid in order to make it work in IE. Here’s his CSS:

ul, li {
	list-style: none;
	margin: 0;
	padding: 0;
}

li {
	margin-bottom: 15px;
}

li li {
	background: transparent url(horizontal-dot.gif) 0 0.5em no-repeat;
	border-left: 1px dotted #000;
	margin: 0 0 0 15px;
	padding-left: 25px;
}

li li ul {
	padding-bottom: 15px;
}

28 March, 2006

Jason Hutchinson suggested to remove the gap by setting the margins to a negative value. A bit dirty😉 but it works in FF and IE. Here are the necessary changes in the CSS:

#sitemap li {
	list-style-type: none;
	margin-bottom:-2px;
}

#sitemap ul {
	margin-top:-2px;
}

26 April, 2006

Robin Parmar suggests a different approach to the problem. He is using more HTML code, fewer images, and comes up with a more flexible solution. Have a look at his suggestion.

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s