A bite of bits

Have a seat and enjoy the madewithlove team's development stories.

Breadcrumbs Navigation in CSS3 – Part 1

A few days ago I decided to try out some different programs to see if my workflow would improve, so I began using CSSEdit rather than Espresso to do the chunk of CSS rules. During my initial tests I noticed a piece of UI that I thought would be interesting to do with CSS3, the breadcrumbs:

Even though there are many techniques that allow us to make something similar to that without CSS3, they all share one single problem: the “arrow” part.

What is the problem with the arrow part? Well, everything in CSS 2.1 or lower is square and flat. There is no way around that.

Since the arrows are oblique, in order to achieve the same effect, we would either place them underneath, or next to each other, and replace the corresponding backgrounds depending on whether the next option was selected or not. Even with use of all CSS3 features, this method is still the most reliable one until this day.

I started off with this html:

<div>
    <ul class="clearfix">
        <li><a href="http://www.google.com/">Home</a></li>
        <li><a href="#">Blog</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Portfolio</a></li>
        <li><a href="#">Contact</a></li>
    </ul>
</div>

My idea was relatively simple: give the list items a border and rotate them -45 degrees, and the links 45 degrees, however, I encountered problems using this idea very early on. First problem was that in order for the part of the border I wanted to show (the corner), the easiest way of doing so would be to turn each <li> into a square, and center it inside the <ul> before rotating it. With that said, I gave the <ul> an overflow hidden, and centered the list items with the following code:

li {
	position: relative;
	float: left;

	width: 80px;
	height: 80px;

	overflow: hidden;

	top: 50%;
	margin-top: -41px;

	-webkit-transform: rotate(-45deg);

	list-style: none;

	background: -webkit-gradient(linear, 75% 0%, 0% 100%, from(#d7e1ed), to(#939ba2));

	border: 1px solid #7f858d;
	border-left: none;
	border-top: none;
}

If you notice, I also gave the <li> an overflow hidden, you’ll understand why in a little while.

Moving along inside the <li> I came across different  problems for the links. They needed to be centered vertically in the <li>, otherwise they simply wouldn’t show up at all. So I gave them a line-height and encountered the second, they were appearing over the arrows of the previous item, and I knew this would be a big issue later on, so I decided to address it straight away.

li:nth-child(1) { z-index: 50; margin-left: -40px }
li:nth-child(2) { z-index: 49; }
li:nth-child(3) { z-index: 48; }
li:nth-child(4) { z-index: 47; }
li:nth-child(5) { z-index: 46; }

Not a very elegant solution, by any means, but I found it to be the simplest one (the margin-left on the first item is to prevent seeing the left end of the arrow on the first element).

Another possible solution would be to use a margin-right/bottom on each item, but due to their oblique positioning I figured that it would too complex of a solution.

With this in hand, and a hover definition on the li, I already had pretty much the effect I desired, except for one small detail: the links weren’t occupying the whole width of the

therefore I made them “stretch” using padding.

a {
	position: relative;
	display: block;

	line-height: 80px;

	-webkit-transform: rotate(45deg);

	margin-top: -10px;
	margin-left: -20px;

	right: -20px;
	top: 20px;

	padding: 0 30px 0 30px;

	color: #494e53;

	text-shadow: 0 1px #e5f0fe;
}

There are many things that needed configuration when righting these rules. If we start from top to bottom:

  • display: block – is necessary in order to rotate the <a>
  • the line-height is for centering it
  • the margins are for nudging the element to the right. We need two margin definitions in this case because the item we’re position the a inside is oblique, therefore we need to use a bit of triangulation. (math was a bit useful after all, dad)
  • the paddings are simply to draw the <a> away from the edges
  • the other definitions are simply decorative ones
So with all that placed together, we would have something that looks like this:

You can see it running here (Webkit-browsers-only at the moment).

The nicest thing about this implementation is that if you position your cursor around the arrows, it will select the correct element with pixel perfect precision. However, the are some serious limitations with this method:
  • All elements have a fixed width
  • Doesn’t degrade gracefully (although a work-around could be achieved using conditional css files)
  • oblique position of the <li> makes it very hard to apply a CSS3 gradient that matches the <ul>’s (though one could easily get around this issue by using a background image.

With these limitations in mind, and a bit of Andreas’ stubbornness as well, we embarked  on a journey to create the ultimate arrow breadcrumbs, with the main goal being to make it the width dynamic.

Stay tuned for the next episode where we’ll attempt to break these limitations.

Filed under HTML/CSS. Tagged with , , , , .

Leave a Reply