Westciv Logo

These materials are copyright Western Civilisation Pty Ltd.

www.westciv.com

They are brought to you courtesy of Style Master CSS Editor and Westciv's standards based web development courses.

Please see our website for detailed copyright information or contact us [email protected].

quick tutorials

A navbar using lists

It's pretty uncontroversial these days that if you need to create a navbar you need to mark up this navbar as a list, using <ul> and <li> elements. This is the only semantically correct way of doing this, and we all know that semantically correct = correct. When I was getting frustrated trying to make this work in the process of doing the Westciv redesign I asked my friend Russ Weakly of Listutorial fame if I could get away with building my navbar as a collection of <p> elements with a million different class attributes. He said, "Maxine, you will get hammered." So, I persisted, and I got there in the end. The navbar at the Westciv site is a nested list which only uses class to distinguish the links to the section and page currently being read. It works in IE 5 and later, Safari, Mozilla etc.

So, I want to save you from a long afternoon of fear and loathing and break the process down and show you how it's done. Actually, the navbar you're going to create here is even niftier than the one at the Westciv site because it uses a little arrow indicator. When you're finished, you'll have created something like this.

The markup

First things first. If you think it's optional to close <li> elements, ie, that things like the following are just fine:

<li>dogs

then you must learn one thing: it's not optional to close <li> elements (or for that matter any non-empty element) in XHTML. It's got to look like this:

<li>dogs</li>

The next thing to learn is how to correctly create lists within lists - what I refer to as "nested lists". The important thing to know here is that, thinking in terms of sections and subsections of your site, each subsection goes in its own <ul>, but this <ul> must always be inside a <li> which is inside the <ul> above. If you think about it this is why a list is so much better semantically in particular if you need your navbar to have subsections. The markup actually conveys something of the relationship between the different items in the list, the hierarchy if you like.

So, if you need a list which is nested down to three levels, as we do on a number of pages throughout the westciv site, in particular within the Complete CSS Guide, you'll need something like the following.

<div id="navbar">

<ul>

  <li><a href="#">birds</a></li>

  <li><a href="#">mammals</a>

    <ul>

      <li><a href="#">humans</a></li>

      <li><a href="#">cats</a>

        <ul>

          <li><a href="#">big</a></li>

          <li><a href="#">domestic</a>

            <ul>

              <li><a href="#">tabby</a></li>

              <li><a href="#">ginger</a></li>

              <li><a href="#">siamese</a></li>

              <li><a href="#">persian</a></li>

              <li><a href="#">grey</a></li>

            </ul>

          </li>

          <li><a href="#">stray</a></li>

        </ul>

      </li>

      <li><a href="#">dogs</a></li>

    </ul>

  </li>

  <li><a href="#">fish</a></li>

  <li><a href="#">reptiles</a></li>

  <li><a href="#">insects</a></li>

  <li><a href="#">arachnids</a></li>

</ul>

</div>

For the basic markup, that's about it. A little later on we will be adding a class attribute, but we try to keep this to an absolute minimum, by taking advantage of the structure of the markup and relying as much as much as possible on descendant selectors.

The CSS

The first thing I like to do, just so you can see where everything is, is to give the <div> that contains the whole navbar a background color. I'm going to make it a pale grey. While you're at it, why don't you give it a width and a border so that it looks a bit more like a bought one. And last of all, I'm going to change the font to sans-serif, just because I find looking at serif fonts onscreen intolerable :-)

#navbar {

background-color: #c8c8c8;

width: 150px;

border: 1px #797979 solid;

font-family: Verdana, Helvetica, Arial, sans-serif;

}

Removing browser default styles

If you take a look in the browser right now it's not looking too promising, but that's mainly because of some styles that are automatically applied by browsers to lists and links. It's easy enough to either get rid of these, or customise them to how you want your navbar to look.

List item indicators

First up, let's get rid of those circles and squares that indicate the list items. We do this using the list-style-type property. This property is applied to the <li> elements and can be used to create all sorts of different indicators, like decimal numbers, roman numbers, squares and many more. In this case though we're going to give it a value of none. What about the selector? The simple answer is that it would just be li, but let's assume you are going to use this navbar throughout your site, and you don't necessarily want to apply this same style to every list in your site. A descendant selector is the perfect tool for this job.

#navbar ul li {

list-style-type: none;

}

Strictly speaking, you don't have to include the ul in the selector above, because this is a simple descendant selector (as opposed to a child selector). However, I'm in the habit of using the full form as much as anything because it makes it easier for you to read and understand what's going on in your style sheet and which elements are affected by which statements.

Anyway, what you've done above should select all the list items in the navbar (no matter what their level in the hierarchy) and strip away that indicator.

Default link styles

Unless of course your name is Jacob Nielsen you'll also want to remove the underlining and electric blue coloring on the links in the list. Again, no need for adding any classes: you can do this with a descendant selector, or at least, two descendant selectors, to select both visited and unvisited links.

#navbar ul li a:link, #navbar ul li a:visited {

color: #797979;

text-decoration: none;

}

This will select all the links in the navbar (again, no matter what their level in the hierarchy) and make them dark grey with no underlining.

Indentation

The last browser default we'll set our own style for is the indentation of those list items. You'll probably want some indentation to indicate to users the hierarchy of the items in the navbar, but not as much as there is now.

First up let's get the space between the outermost list items and the edge of the whole navbar down to a minimum - say 3 pixels. Don't worry that it looks a little tight at the moment, we're going to do something a little later that will change this. Now you might think that what's causing all that extra space at the moment is margin. You'd be half right because in IE6 this is the case. However, in all other browsers it's actually padding that's doing this. So, the way to get the effect you want in the maximum number of browsers is to bring the margin-left back to 0, and then add 3px of padding-left.

#navbar ul {

padding-left: 3px;

margin-left: 0;

}

Making the navbar make sense

OK, that should be looking better now. But I think we need to create a bit more indentation than 3 pixels to indicate the different levels in the hierarchy, while leaving the distance between the outermost links and the edge of the navbar box at 3px.

Does this mean then that you have to create an individual rule for each of the different levels of nesting? Well, you would if you wanted to have different left margins at each level. But you don't. All you want is for each level to be indented a further 12 pixels than its parent, but for the outer <ul> to remain only 3px from the edge of #navbar.

So all you have to do is select <ul>s, that are inside <li>s that are inside <ul>s that are inside #navbar. And then all levels of nesting will get this same indentation.

#navbar ul li ul {

margin-left: 12px;

}

The different levels in the hierarchy still aren't distinguished from each other strongly enough in my opinion. I think it would look better if we made the lowest level a slightly smaller font size and gave it a different color as well. This would also let you emphasise the subsection of the site that the user is currently in. What selector do you need to do this? Can you count down through all those <ul>s and <li>s to the lowest level? And remember at the end you'll also need to select the link in order to over ride the black color you've given to all links in the navbar above.

#navbar ul li ul ul li ul li a:link, #navbar ul li ul ul li ul li a:visited {

color: #ff0000;

font-size: 80%;

}

Makes it stand out a lot better doesn't it?

Letting users know where they are

One of the best things I did when I created the current Westciv site was to implement a much improved system for helping visitors understand exactly where they are in the site at any time. I do this by making the link in the navbar bold and adding on a large left border. In this tutorial we're going to achieve this same result a little differently.

This is the the only time where you're going to have to add a class into the HTML. There's simply no other way of selecting an individual one of those <li>s. So, go back into your HTML and choose one of the <li>s at the most nested level and give it a class of "current".

<li class="current"><a href="#">siamese</a></li>

The user will know exactly where they are because a little arrow will appear beside this section. How? My favourite CSS property for weaving all sorts of magic: background-image.

We want to apply a background image to the links (both visited and not) which are inside <li>s of class current.

#navbar ul li.current a:link, #navbar ul li.current a:visited

Now, all I need do is give this selector a background image, make it not repeat, and also make it appear on the left, centered vertically.

#navbar ul li.current a:link, #navbar ul li.current a:visited {

background-image: url(arrow.gif);

background-repeat: no-repeat;

background-position: left center;

}

If you've looked in the browser you'll see there's a small problem, isn't there? The background image is being drawn under the linked text, not to its left. We can overcome this by adding some padding to compensate, but we actually want to do this to all the links in the navbar, otherwise the current one will seem like it is indented compared to the other items in the list. You already have a statement that selects all the links in the navbar, just add the padding to its list of properties.

#navbar ul li a:link, #navbar ul li a:visited {

...

padding-left: 15px;

}

Now, can we go one step further and make the arrow also appear when you rollover the links in the navbar? This is really easy: just add another selector to the group selector we created before.

#navbar ul li.current a:link, #navbar ul li.current a:visited, #navbar ul li a:hover {

...

}

And there you go. What do you think of that? We've now got an excellent little navbar, totally lightweight, minimal use of classes, maximum usability, maximum semantic sense. A very good outcome indeed.