Simple Horizontal Navigation

Note: This post was originally written 3+ years ago and in web development years, that is an eternity. I have redone the snippet to use better CSS and I explore two different methods for making the navigation horizontal on large screens. I’ve also made the snippet responsive. It will create a vertical menu on smaller screens and a horizontal menu on larger screens.

Preferred Learning Method?

Code Snippets
If you just want the code and don’t need a description.

Watching a Video
If you like being shown how something works with some explanation watch the video.

Reading a description
If you learn better by reading, I am including the transcript of the video with corresponding code snippets embedded.

Code Only

HTML

CSS

IE 8

Video

Transcript

Let’s start with the HTML. I have a simple un-ordered list of links. Each list item has a class name related to its name.

    <div class="nav">
      <ul>
        <li class="home"><a href="#">Home</a></li>
        <li class="tutorials"><a href="#">Tutorials</a></li>
        <li class="about"><a href="#">About</a></li>
        <li class="news"><a href="#">Newsletter</a></li>
        <li class="contact"><a href="#">Contact</a></li>
      </ul>
    </div>

I’ll use a mobile-first approach and start styling this list as a vertical navigation so it will look good on phones and smaller tablets.

I’m clearing out margin and padding and giving a background color to the body first.

    body {
      margin: 0;
      padding: 0;
      background: #ccc;
    }

Next I’ll style the list to remove the bullets and give it a background color. I want the text centered. It doesn’t look perfectly centered yet, but if I remove padding it will. Clearing the margin will make it hug the top of the page which I want.

I am targeting ul inside of .nav because I would probably want different styling on non-navigational unordered lists.

    .nav ul {
      list-style: none;
      background-color: #444;
      text-align: center;
      padding: 0;
      margin: 0;
    }

On the list items inside of nav (.nav li) I will set the typography.

    .nav li {
      font-family: 'Oswald', sans-serif;
      font-size: 1.2em;
      line-height: 40px;
      height: 40px;
      border-bottom: 1px solid #888;
    }

I’m setting the line-height and height both to 40px so that the text is centered vertically on each line. I also am giving a subtle border to distinguish the lines.

Finally, I’ll turn off the underlines and make the text white in the links.

    nav a {
      text-decoration: none;
      color: #fff;
    }

Again I’m only targeting anchor tags inside of .nav, because I don’t want to assume all anchor tags will be styled this way.

The links are only clickable when I am actually on top of the words in the link. I want the link to span the entire block. So I need to add display: block to these links. Now I can click anywhere to go to a different page.

I’d like to make the color different when we hover over the link. I can do that with this:

    nav a:hover {
      background-color: #005f5f;
    }

It would be nice to have a little transition effect on the hover as well, so I will add that.

    transition: .3s background-color;

I add it to the a tag though and not the hover selector. This will allow the transition to happen both when you mouse over the link and also when you move your mouse away.

The final thing I want to do before styling the wider screen navigation and making it horizontal, is to style the active class.

I have an active class on the “news” link right now. I can style the active links with this.

    a.active {
      background-color: #fff;
      color: #444;
    }

But we have a problem when I hover over the active link. I don’t want that color to change. So I will add .nav at the beginning so this selector has more specificity and will override the .nav a:hover that was previously defined.

I’d like to change the cursor: default; so it doesn’t look like clicking on this link will do anything.

So things are working nicely, and this would look fine on a phone. However, if we are on a wider screen, it looks strange.

When the screen is larger than 600px I’d like to switch to a horizontal navigation, so that will be my break point.

Anything less than 600px will show navigation vertically, and anything with more resolution will show it horizontally.

I can add a media query.

  @media screen and (min-width: 600px) {

  }

Then I can target the .nav li inside of the media query. So when on a screen that is at least 600px wide it will use this code:

    .nav li {
      width: 120px;
      border-bottom: none;
      height: 50px;
      line-height: 50px;
      font-size: 1.4em;
    }

I am making each menu item 120px wide since there are 5 items and 5*120 is 600. I’m removing the border and making the menu text and bar just a little bit larger.

If we move the viewport a little we can see how it changes.

Now we have two options for making this horizontal. One option is to display the list items as inline-block, and another option is to use floats. The first method is simpler but you may have a reason for wanting to use floats, so I will explain both options. Either option will work on IE8, however, IE8 will not understand the media query. So later we will need to copy this code to an IE8 only style sheet.

Even though I’m still targeting the .nav li selector, I’ll put the different option code outside of this first selection so I can easily distinguish between the two options.

If I add

    .nav li {
      display: inline-block;
    }

the navigation works pretty well. We do have a slight problem around 600px wide where the last menu item jumps to another line. Also, if I hover over the other items, you can see we have this little gap of gray showing. That is because when using inline-block there is a bit of margin that is introduced. We can deal with it, by adding a small negative margin.

    margin-right: -4px;

And now everything looks great.

So this method works, and we could stop there. I’m not sure if there is a down-side to this, but you might want another option and see how floats would work.

    .nav li {
      float: left;
    }

And this almost works, but the gray bar disappeared. That is because the parent element collapsed when the children where taken out of the flow by floating them.

If I turn on the Live Preview Highlight, you can see each li tag with it’s border. But the ul tag, is just this one line here which means is it collapsed.

There are numerous ways to fix this, and I have an entire video explaining all the ways. In this case, I will just add

    .nav ul {
      overflow: auto;
    }

which is simple and will work.

However, we have a new issue, and that is that the navigation is not centered anymore. Depending on your website, this might not be an issue. But if we want to fix this we can add this:

    width: 600px;
    margin: 0 auto;

to center it.

And one final change is to make the entire nav bar have the dark gray color so it extends.

So, the inline-block method is a lot less code and simpler. But I thought it might be useful to see both methods. I used to always use the float method and getting it right sometimes caused headaches.

Finally, this code works well in all modern browsers, including IE9 and above. If we looked at this in IE8 we would only see the vertigal navigation like this, regardless of how wide the screen was, because IE8 does not recognize media queries.

To make it work in IE8 we can use a conditional style sheet and add the code we just added to our media query.

<!--[if lt IE 9]><link rel="stylesheet" href="ie.css"><![endif]-->
    .nav li {
      width: 120px;
      border-bottom: none;
      height: 50px;
      line-height: 50px;
      display: inline-block;
      margin-left: -4px;
    }

This won’t ever display the vertical navigation in IE Browsers, but it is unlikely anyone using IE would be viewing this on a phone, so it should be okay.

If I had styled the horizontal menu first, we wouldn’t need an IE specific style sheet. I could have used a max-width instead of a min-width and flipped how I wrote the code. But I wanted to take a mobile first approach. The code ended up being simpler than when I approached it from the larger screen originally.

I hope that was helpful, if you have any questions, please post them at css-snippets.com.

CSS Animations

There are two ways to animate things with CSS. One is with the transition property. The other way is with the by creating a keyframe animation and the animation property. This video and article are referring to the Animation method.

CSS Animations require two things to work. First you need to set up the animation and it’s keyframes. Second, you need to call or use the animation and set up it’s properties, such as the duration of the animation, how many times it should run, it’s easing method and more.

Set Up the Animation

As of today, only webkit browsers need the prefix. IE, Opera, and Firefox all work off of the un-prefixed code.

Fade In and Out

Shrink and Grow

Move

Change Colors

Use the Animation

Performance

There is a lot of discussion around what is better to use for animations – CSS or Javascript. I don’t really have the answer to that. Animations are a complex topic and in general you may need to factor in the type of animation you are creating, who your audience is, and what devices the site is viewed on, etc. If you want to read more about performance, you can try this article: High Performance Animations or this one: Myth Busting Mythbusted

Browser Support

CSS Animations work in IE 10 and above. They also work in all other modern desktop browsers. On mobile devices they work in everything except Opera Mini. See caniuse.com for specifics. If it is important that your animation works in earlier versions of IE, you may still want to use Javascript for your animations.