CSS navigation with diagonals

Sometimes when I look at the twitters i find little requests for ideas on how to do something. I often do this to, usually for jQuery. Today Mark Skinner wondered this -

Any suggestions on how to achieve work.kevinleary.net/diagonal-nav/d… without using the JQuery? :-)

— Mark Skinner (@MarkSkinner_) May 7, 2012

As soon as I clicked the link I instantly thought that a navigation system (menu) like this could be created in pure CSS

I found myself with a free half hour so I thought I'd crack open JSFiddle and have a go to see what I could come up with. Please note: there are other online places and spaces to quickly code up simple things, I just am so used to the 4 windows of JSFiddle it's hard to try anything else (for now).

The Code Begins.  

First up I obviously needed to create the HTML for the menu. I knew in my CSS I was going to be using display: inline-block; on the <li> elements so I wrote this example HTML.

<ul>
    <li><a href="">link 1</a><li>
    <li><a href="">link 2</a></li>
    <li><a href="">link 3</a></li>
    <li><a href="">link 4</a></li>
<ul>

What i did to the above examples was put all the <li> elements on a single line of code. Simliar to this -

 

<ul>
    <li><a href="">link 1</a><li><li><a href="">link 2</a></li>
</ul>

By putting the <li> in one line with no gaps we would not inherit a 4px gap that inline-block gives us by proxy. 

CSS Set-up.

For years I've used Eric Meyer's CSS Reset in the various guises it pulled and only recently (the last 3-4 months) have I side-lined it for Nicolas Gallagher's Normalize system. So first off this is including in pretty much every CSS file I create and (luckily) it's also included in new default JSFiddle page.

Secondly I now add the new cool box-sizing CSS property which that Paul Irish discusses in this blogpost


* {
  -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
     -moz-box-sizing: border-box; /* Firefox, other Gecko */ 
          box-sizing: border-box; /* Opera/IE 8+ */
}

And to start.

Next I wrote a little bit of CSS. This would be to style the <ul> and the <li> elements and can be changed to suit -


ul { 
  background: grey; 
  height: 60px; 
  padding: 10px 0 10px 40px; 
  width: 100%; 
}

li { 
  background: orange; 
  float: left;
  line-height: 20px;
  margin-right: 30px;
  padding: 10px 3px;
  position: relative;  
}

As you can see I've added a margin-right to all the

elements so I need to tidy that up a bit with some CSS3 Pseudo Selectors. This would be just to remove the last margin-right property from the last element-


li:last-of-type { margin-right: 0px; }

Triangles

Ok, so now that each navigation element has a 'block' of colour I wanted to start adding the 'diagonal' parts to it. To do this with CSS I used the :before and :after elements of CSS 2.1 and created this bit of code -


li:before {  
    background: none;
    border-left: 20px solid transparent;
    border-right: 0px solid transparent;
    border-top: 40px solid orange;
    content: "";
    left: -20px;
    position: absolute;
    top: 0;
}

li:after { 
    border-left: 0px solid transparent;
    border-right: 20px solid transparent;
    border-bottom: 40px solid orange;
    content: "";
    height: 0;
    position: absolute;
    right: -20px;
    top: 0;
    width: 0;
} 

Hover

So, as it's a little bit of navigation it's best that I add some kind of hover effect to it. To do this there's some funky CSS that need's to be added so the whole kaboodle will change colour on hover.

First off we add display: block; to the <a> element, we might as well get rid of that nasty text-decoration too -

a { 
  color: black;
  display: block; 
  text-decoration: none;
}

Now we've done that we can just change the bits we need to change for the hover effect. This would be for the actual <li> element and it's :before and :after pseudo bits too.


li:hover { 
  background: white;
  cursor: pointer;
}   
li:hover:before { 
  border-top: 40px solid white; 
}
li:hover:after { 
  border-bottom: 40px solid white; 
}

As you can see I've 'stacked' the pseudo selectors 'on top' of each other so that when 'hovered over' the whole dang thing changes colour.

We could have finished there.

Looking back at the original link Mark tweeted we can see that the first link (home) doesn't have a diagonal on the left only on the right. So to create this effect we need to add this bit of CSS -


li:first-of-type:before {
    background: orange;
    border: none;
    height: 40px;
    left: -10px;
    width: 10px;
}

li:first-of-type:hover:before { 
    background: white; 
    height: 0px;
    width: 10px; 
}

This removes the border which was making the triabgle and adds a simple rectangle of colour

A Step roo far?

After doing this quickly I though it'd be nice to 'finish off' the navigation's design with a similar effect to the last

element. Just like this -

li:last-of-type:after {
    background: orange;
    border: none;
    height: 40px;
    right: -10px;
    width: 10px;
}
li:last-of-type:hover:after { 
    background: white; 
    height: 40px; 
    width: 10px;
}

That's about it.

Doing all this has created a nice little CSS navigation effect.

Of course there are some gotcha's.

  1. It's not 'responsive', I'm of the thinking that you'd switch up the styling of navigation for smaller viewports anyway so this wouldn't be a problem.
  2. It can break, of course it can. If the menu is longer  than the viewport, it'll break. I may refine this bit. I may not.

I've tidied it up a little bit and the final JSFiddle is available to look around and poke at.