Thursday, January 23, 2014

How to Code an Elegant Breadcrumb Navigation Menu With Arrows (using only CSS)

So, you want a great-looking, flat-design, arrow-like breadcrumb navigation? Something withoput images? Look no further!

This is what it will look like
Let's dive into:

Let's start with a simple navigation item, with links inside. We will need some extra HTML. Hence, we will insert three <span>s into each <a> element. One for the upper half of the link, one for the lower half, and one for the actual content.


<nav class="navigation">
    <a href="/start" class="active">
        <span class="upperArrowElement"></span>
        <span class="lowerArrowElement"></span>
        <span class="content">Getting Started</span>
    </a>
    <a href="/start/signup">
        <span class="upperArrowElement"></span>
        <span class="lowerArrowElement"></span>
        <span class="content">Sign Up</span>
    </a>
    <a href="/start/signup/enjoy">
        <span class="upperArrowElement"></span>
        <span class="lowerArrowElement"></span>
        <span class="content">Enjoy</span>
    </a>
</nav>

The magic happens, when we insert the right CSS. I would like first to describe, what actually happens:
We will use some fancy CSS properties to style first and second <span> to look like the arrow. The content will be displayed via span.content . The first element will need some extra style so that is has an straight vertical border.

So, let's start with the CSS:

nav {
    font-size: 13px;
}

.navigation a {
    display: block;
    position: relative;
    float: left;
    height: 32px;
    box-sizing: border-box;
  
    margin-right: 2px;
    margin-bottom: 5px;
  
    text-decoration: none;
    font-family: sans-serif;
    color: #333;
}

We will need to position the children elements by position:absolute. Because we don't want to position the arrows relative to the navigation menu, but relative to each link item, we need to set position: relative; . Another important value, that should be set is (suprprise!): height. If we set height so an uneven value, there might be ugly artifacts in some browsers (I will explain later).

Now let's go to the next point: The real arrow stuff (Hooray!)

.navigation a > .upperArrowElement {
    display: block;
    width: 100%;
    height: 50%;
    position: absolute;
    -webkit-transform: skewX(35deg);
    -ms-transform: skewX(35deg); /* IE 9 */
    transform: skewX(35deg);
    background-color: #E5E6E8;
}


This is the part where the real actions happens. We set the width to 100% and height to 50% and set the position to absolute (Therefore we need to set position of the parent element to relative).  We transform the the upper element by transform: skewX(35deg); This forms the upper part of the arrow. We really should set the height of the parent element to an even pixel number, because Firefox and Internet Explorer will leave some sort of half-pixel transparency on the top and bottom edge of the .upperArrowElement if you use skewX. The lower part, we handle analogously: We transform the bottom part in the opposite direction and position it at the bottom part of the link.

.navigation a > .lowerArrowElement {
  display: block;
  width: 100%;
  height: 50%;
  position: absolute;
  bottom: 0;
  -webkit-transform: skewX(-35deg);
  transform: skewX(-35deg);
  background-color: #E5E6E8;
}

We position also the content:

.navigation a > .content {
  display: block;
  padding: 0.5em 1.3em;
  position: relative;
  top: 0;
  left: 0;
}


When we look at the navigation bar, it looks like this:

Without straight vertical line
If you like it, you're done. But if want the vertical line, you need a little bit more CSS. But don't fear, you won't need any additional markup.

.navigation a:first-child > .content {
  left: -2px;
}

We should slightly move the content of the first link. It will look better. Trust me.

.navigation a:first-child::before {
    content: '';
    display: block;
    position: absolute;
    background-color: #E5E6E8;
    height: 100%;
    width: 50%;
    top: 0;
    left: -5px;
    z-index: -1;
}

Some explanation: We add an element to the first a. We position on the a little bit to over the left edge of the parent element and make it below the parent a (oh, yeah this is another reason we need to position the parent a: to make the z-index property work).

Aaaaand we're done! Here's the complete code, including live demo The beauty of this approach is manifold:
  • We need no images. Especially for people who don't know Photoshop, GIMP this is a big plus.
  • We need no images. Want the arrows a little bit shaper? Just change the angle. Move the ::before block a little bit to the left. Just some keystokes and you're done. Compare that to your Photoshop image replacement.
  • This is my favorite part: Hovering on the arrow links is pixel perfect. I haven't found that on the internet yet. Not even on hongkiat.com (which is usually great for such stuff).
  • Did is say, we need no images? Design in browser. Be awesome.

No comments:

Post a Comment