Feb 10
Simple scalable CSS based breadcrumbs
2009 at 03.42 pm posted by Veerle Pieters
A few days ago I was implementing breadcrumbs in a website I’m working on. Not that I sincerely believe every site needs this, but on some occasions and to some users breadcrumbs are practical. Anyhow, it gave me the idea to write an article about it because it’s been a while since I last wrote about anything CSS-related. The one I’ll share with you is a very simple one. It uses only one simple graphic. The rest is basic CSS styling with an unordered list as HTML code.
![]()
The one I implemented in the project I'm working on looks a bit similar, but was more complex to code. More CSS classes and a span element were needed to make it work. I thought I stick to a very simple one, a bit like the one Apple is using.
The HTML code
Here is our HTML code. It's a simple unordered list:
<ul id="crumbs"><li><a href="#">Home</a></li><li><a href="#">Main section</a></li><li><a href="#">Sub section</a></li><li><a href="#">Sub sub section</a></li><li>The page you are on right now</li></ul>
All items have links, except the page you're on. While working on this, I wondered if a list is the most 'appropriate' structured code to use for breadcrumbs. I don't think there is a strict rule here, but I believe using a list is a meaningful way and so semantically I believe it's appropriate.
The CSS
Here is the CSS styling:
ul, li {list-style-type:none;padding:0;margin:0;}
First we reset the basic list styling behavior: hide the typical round bullets that appear by default and remove the indentation by setting the margin and padding to zero.
#crumbs {border:1px solid #dedede;height:2.3em;}
I've given the list an ID called #crumbs. I've add a border around the breadcrumbs and set a specific height.
#crumbs li {float:left;line-height:2.3em;padding-left:.75em;color:#777;}
All crumbs need to appear on 1 horizontal line so we give each li element float:left. The text needs to be center aligned vertically, so we use the same value for line-height as we did for the height of the list which is 2.3em. To leave some space to the left in between each crumb we add a padding on the left of 0.75 ems. Next, we add the color of the text.
#crumbs li a {display:block;padding:0 15px 0 0;background:url(images/crumbs.gif) no-repeat right center;}
We want to have the entire arrow area clickble. To do this we give the a element display:block. We add the background image to the a element. The image looks like this:

It is a rather big image, but that's because we want it to be scalable. The background image is positioned to the right and vertically centered. So when the user enlarges the text in his browser the corner of the arrow will always stay nicely vertically center aligned.
#crumbs li a:link, #crumbs li a:visited {text-decoration:none;color:#777;}
Add the styling for the text links. I've used text-decoration:none to hide the underlining and I've used a soft color just to to draw not too much attention to these.
#crumbs li a:hover, #crumbs li a:focus {color:#dd2c0d;}
Then last but not least add the text styling when the user hovers the crumbs. If you want to have the underlining appear again on hover, just add text-decoration:underline.

56served
1
As always your examples are great. This is such a clean implementation of a breadcrumb trail. The code and the visual side of it.
Thank you!
2
I think I’ll implement this into some future website templates. Thanks for the simple and helpful tutorial Veerle.
3
On breadcrumb semantics, the SimpleQuiz had a chapter about breadcrumbs.
4
Well done Veerle, looks pretty nice! Reminds me of the Apple-like breadcrumb CSS menu explained by Janko.
Keep up the good work!
5
That is pretty cool :-)
6
I really like the idea of using a big image that scales up.
Does anyone know what browsers increase text but not images? (good for this) And what just zoom everything? (still pixellates the image)
I “think” Safari increases just text while FF and IE zoom everything as default behaviour on Windows.
7
Beautiful.
If you set
padding-righton theaelement value in ems instead of pixels, it’ll retain it’s dignity even at HUGE text sizes.8
Very useful, thanks :)
9
Try doing this:
1) Move the left padding from the li to the a.
2) Add a left margin to the a of -.075em
This ought to fix the display issue with the first breadcrumb (Home) where its background suddenly changes from gray gradient to white just to the left of the text.
Way to make this solution scalable with text size :)
10
Thanks!
One suggestion: since the breadcrumb essentially displays a kind of hierarchy, it might make some sense to use an ordered list instead of an unordered list. (But it’s hardly something to obsess over.)
11
Hi Erik,
Along the same lines, would nested uls with one li per level be more appropriate as it represents hierarchy while lis of the same ul represent equality?
12
I was about to post the same comment as Erik, then I saw his.
An ol would seem more appropriate based on the hierarchical nature of a breadcrumb trail. But I’ve never implemented a breadcrumb list before - so you’re one ahead of me.
Thanks for your HUGE contributions to the community! You do amazing work.
13
Very nice! Thank you very much.
14
Excellent article, thanks a lot!
Can’t wait for the first opportunity to implement it…
15
Very nice. I almost wonder if maybe a nested list is the most semantic, since each sub-item is a child of its parent. The HTML wouldn’t be much bigger, with just the addition of ULs around each LI. Anyway, just a thought. Looks great!
16
In the WCAG2.0 there’s a Part about breadcrumb trails and they suggest (as I understand it) not using complex but a rather simple markup:
http://www.w3.org/TR/2008/NOTE-WCAG20-TECHS-20081211/G65
I don’t know which one would be more appropriate but I guess in text- and audiobrowsers a list-style Breadcrumb trail uses too much time/space.
But that’s just guesswork.
17
Another vote for using an ordered list.
And while nested lists might be the most semantically correct, they would involve an unnecessary amount of markup.
18
This works great in a perfect world, where your clients do not have pages with long, long titles… And when the breadcrumb is too long to stay in a single line it crashes…
But anyway, I always appreciate your work ! :)
19
Thank you everyone :)
Art Lawry said:
Oh, I actually didn’t notice this until you mentioned this here. Thank you for the tip ;)
Erik Vorhes said:
I thought about using an ordered list too, but then I thought would that make ‘more’ sense? Also, if you start thinking about it, you would actually need to code a nested list, because then you get the right hierarchy, but wouldn’t that be a bit over the top?
Art Lawry said:
Yes exactly my thinking too. I see some other people think the same as well. Not sure if I would go that far though :)
maweki said:
Thank you for the info. I guess you could use 1 div for the breadcrumb and spans around each crumb (to add styling), then maybe hide the separator via CSS? Not sure, I just like more graphical styling instead of having it appear as pure text.
Chiara said:
That’s why I said in the beginning that some sites needed and others don’t :) I see breadcrumbs as a last resort and will try to tackle the root of problem first before using them. However in some cases the client insist on using them and than it is a matter of watching the users to see if they really improve things. When it is really long you can also just resort to a simple ... ;)
20
I like that approach. But would you even need spans? A
pordivwithas looks like it would work, with aspanonly for “the page you are on”.(I only did a Q&D test with firebug, though, so don’t take my word for it)
21
It’s better this way, when CSS turned off it’s still ledgible.
22
Lieven said:
Not sure if I follow you here, a list is still legible imho. If you think otherwise than all navigation on most sites isn’t.
23
I meant that a list is better, when the CSS is turned off , then a div. There is more coherence. When div’s are used the “breadcrumb” falls apart, codewise.
I thought you wanted to replace the li with a div… or isn’t that correct?
24
Lieven said:
Yes because the WCAG 2.0 recommends keeping it simple (see comment) , so not using a list. That’s why I said I would resort to a div (for a more graphical look) in combination with spans and hiding the > via CSS. So it still would make sense even with the CSS off. WCAG is the source for accessibility so that’s why I was thinking along those lines :)
25
Great article. I’ve been playing around with somethig similar but I’m using a CSS sprite so that the background image changes slightly on hover. Seems to work pretty well.
26
Lovely tutorial! Clean and simple.
27
Thanks for breaking into small comprehensible steps. Reminds me that the CSS elephant is much easier to eat one bite at a time.
28
That is a hella clever technique to get the gradient and scaling. Thanks so much for sharing this!
29
Great article. It’s exactly what I’ve been looking for. Thanks a lot!
30
Very nice tutorial, this will surely come in handy one day :)
31
Very very cool!
32
I really like this design. It is simple and pretty. The mark up needs no arguments, a list is definitely the best way to implement a breadcrumb.
However, I’m not sure if the design would work if “the page you are on now” had a long title that would wrap on to two lines. That is something web designers must consider when handing over the site to a client.
[Edit Veerle: This has been already addressed in this comment]
33
As usual, a concise and useful tutorial with a great end result.
I’ve always been more of a fan of not setting the container (ul in this case) height and instead adding an overflow: hidden or similar clearfix. That way your height is only in the CSS once. Tiny point, though.
34
Very useful, and very close to how I do it. While the html is almost the same (I rather prefer to use only classes except when javascript is involved), my css applied to your code would be:
ul, li {
list-style-type:none;
padding:0;
margin:0;
}
#crumbs {
display:inline-block;
height:2.3em;
border:1px solid #dedede;
padding-right:0.75em;
}
#crumbs li {
display:inline-block;
line-height:2.3em;
color:#777;
}
#crumbs li a {
background:url(images/crumbs.gif) no-repeat right center;
display:block;
padding:0 15px 0 0.75em;
}
#crumbs li a:link,
#crumbs li a:visited {
color:#777;
text-decoration:none;
}
a:link, a:visited,
#crumbs li a:hover,
#crumbs li a:focus {
color:#dd2c0d;
}
Basically:
- I’ve added padding-right to #crumbs
- I’ve added display:inline-block; to #crumbs
- Removed float from #crumbs li
- Removed padding-left from #crumbs li
- Added display:inline-block; to #crumbs li
- Changed padding:0 15px 0 0; to padding:0 15px 0 0.75em; from #crumbs li a
I added display:inline-block; and padding-right:0.75em; to #crumbs because I normally share the area or the line for the breadcrumb with something else (like a date or a version number) on the right hand side, or because I want to set a fixed width of the ul#crumbs avoiding the clearing problems.
35
Excellent ! very usefull combination of a static navigation and a breadcrumb !
36
a little disappointed at how basic this post is but perhaps there are still people who haven’t coded breadcrumbs before.
ordered list would have more semantic value because the order of the items is important in a breadcrumb. if you change the order then you change the meaning. hence, ordered list is preferable over unordered list.
37
If you’d want to remove the-sometimes-bothersome dotted rectangle around each li-link, you could add
outline: none;on the a-styling.38
koew said:
The dotted outline on links is the main visual cue to where the current keyboard focus is on a page. By tabbing or shift-tabbing through the document the focus is set on the next or previous focusable elements. So they serve a very useful purpose and that purpose is critical for a sighted keyboard user to find their way through a page. Removing it is not done since it is an accessibility feature.
39
I was looking for a clear example like this, so thanks a lot :)
40
I’d then rather do a more visual hover-effect instead. For instance a background color change or something eye-catching, by using the
:focuspseudo-class.If you really want the sighted keyboard user to easily recognize where they are on the tab-index, make it stand out more. Wouldn’t it be tough on the person with lowered sight/vision to look around for the dotted corners?
41
koew said:
It is funny that you first say it is bothersome and type a tip to remove it and now you are back suggesting on improving it. Quick turnaround :) It’s already good the standard way otherwise they wouldn’t have implemented it but I like to keep things in balance when thinking about accessibility. Given it a very visual focus will affect other users as well so that’s why I try a moderate approach.
42
If you do a sliding doors-trick on the breadcrumb, you could end up with a decent hover-effect that wouldn’t destroy the design for regular users.
And yes, I did turn halfway that’s true. I still would’ve replaced the dotted rectangle.
I partly agreed with your reply and wanted to add some suggestion on making it even more visual/helpful. I’ve worked on accessibility for some time for some clients, and I know it’s important.
The tutorial is a great one, and I really enjoy the scalability-factor you’ve included on the image, making it flexible! How does it cope with IE6’s text resizing?
43
Awesome tutorial. So simply executed and easy to follow. Thank you!
44
Great simple and effective breadcrumbs with CSS. I like the use of the enlarged arrow graphic to allow for scalability. I first came across this idea in Dan Cederholm’s ‘Bulletproof Web Design’. I wonder if you created the breadcrumbs dynamically via filenames or if you hard-coded each trail on each page? If anybody is interested you can see a PHP script on my blog that dynamically creates a breadcrumb trail based on the pages filename and location. Cheers!
45
I love your blog. I learned about it from a web teacher a year ago and I have learned so much from you.
Now I have added your blog to my rss reader. What took me so long?
Thanks for all you do!
46
Love this effect. It has the Veerle feel to it.
Especially love the simplicity and the visual effect of the arrows.
47
Very clear explained! I like the use of the big background-image. Smart solution!
48
Nice CSS tip. The WordPress theme “iNove” also uses this well. Anyway, thanks for sharing. I’ve been reading your blog for quite a long time. :)
49
The argument between ordered versus unordered lists is one of minutae really. I know you want to be semantically perfect but either will do.
Nested lists would be a little tedious for a screen reader because it would read out the fact that it was a new list and how many items were in that list for each link.
50
Nice tutorial, very simple. Thanks for sharing your wisdom with us.
51
Thank you. Simple yet great tutorial.
52
Nice post! I like it…. I might just end up using this for all our new Doodlekit layouts. Thanks!
53
Excellent article, thanks. I like your large background-image-idea a lot!
One word to the ul: if you skip the fixed height of it and let the ul (parent of floating li’s) float, too, it will automatically fit its size to multilines. Just have to put a width to the ul, so it “surrounds” all li’s
instead of
#crumbs {
height: 2.3em;
}
use
#crumbs {
/* height: 2.3em; */
float: left;
width: 100%;
}
54
Breadcrumb links are great for seo and also provide a lot of value to users. I have been looking for a way to dress them up a bit. This is perfect.
55
Inexplicably, I find myself on your site for the third time in 24 hours. First I was looking for color calculators, then I wanted to spruce up a table, and now breadcrumbs. You’ve blown me away. Keep up the incredible work.