Create a notched current-state nav

Ben Everard tweeted last night asking if anyone knew how to build a notched nav, like this. I was in bed at the time, I spotted it about midnight and was on my phone. As soon as I saw this I jumped out of my bed and turned my Mac on. I love stuff like this!

Anyway, this is my solution, and this is its code.

Basically there are two main parts to this technique; the punching-the-hole-through-the-nav and the masking-the-hole-to-be-a-triangle. Both techniques couldn’t be simpler, and we use pseudo elements to do it.

Punching holes through elements

This whole technique can only work by taking advantage of the behaviours of fixed background images. The exact same background:; applied to two elements give an odd result if both are also fixed. It gives the effect of a hole having been punched right through your page to the background…

What we do here, then, is create a pseudo element with .nav .current a:before and sit this at the bottom of the current list item. We then apply the fixed background to this as well as the page. This is our punched hole already sorted, only it’s square… we want a triangle.

Masking the hole

To mask the hole to appear like a triangle we use another pseudo element and the CSS triangle hack to cover things up.

The triangle hack works by selectively applying borders to zero width/height elements, take a look at this version with the triangles highlighted. All we need to do here is make some of them the same colour as the nav and we’re done!

So, by cleverly using a pseudo element we can spoof a hole through elements and then using a second one we can mask the corners off!

The full, commented CSS:

.nav{
    overflow:hidden; /* To clear floats */
    background:#111;
    margin:0;
    padding:0;
    list-style:none;
}
.nav li{
    float:left;
}
.nav a{
    display:block;
    padding:2em /* <-- This is our magic number, this defines how large our notch can be! */ 1em;
    color:#fff;
    text-decoration:none;
}
.nav a:hover{
    text-decoration:underline;
}
.nav .current a{
    position:relative;
    text-decoration:underline;
    cursor:text;
}
.nav .current a:before,
.nav .current a:after{
    content:"";
    display:block;
    width:2em; /* Must match our magic number... */
    height:2em; /* ...our notch will end up being half this size. We define it in ems to scale it up with the text size. */
    position:absolute;
    bottom:0;
    left:50%;
    margin-left:-1em; /* Half of our magic number. */
}
body,
.nav .current a:before{
    background:url(http://farm5.static.flickr.com/4102/4876702379_82fe2bd7a8_b.jpg) top left no-repeat fixed; /* Apply to the notch and the relevant container (this case, body). */
}
.nav .current a:after{
    width:0;
    height:0;
    border:1em solid #111; /* Half of our magic number and same colours as our nav’s background. */
    border-bottom-color:transparent;
}

Drawbacks

There are drawbacks here; you have to have a fixed background image and you have to have a solid background colour for your nav, but they are reasonable trade-offs, considering this doesn’t use any extra markup at all and works in IE8+!


Did you enjoy this? Hire me!

Hi there, I’m Harry. I am an award-winning Consultant Front-end Architect, designer, developer, writer and speaker from the UK. I write, tweet, speak and share code about authoring and scaling CSS for big websites. You can hire me.


I am currently accepting new projects for Q1, 2015 Referral scheme


Projects

  • inuitcss
  • ITCSS – coming soon…
  • CSS Guidelines

Events

I am available for hire to consult, advise, and develop with passionate product teams across the globe.

I specialise in large, product-based projects where performance and CSS scalability and maintainability are paramount.