This is a quick CSS tutorial to show you how to create a menu list using either the CSS border style or a background image. The trick is to apply a bottom border to the <li> element, then use the absolute position property to shift the nested elements down to cover the border. It is very flexible — you can easily change the layout by altering the border or background image. It even works when the browser's font size is being scaled (increased or decreased).
1. HTML Code
Take a look at the HTML code and the diagram. They will help you understand how the CSS work.
<ul>
<li><strong>CSS Design</strong> <em>250<sup>95</sup></em></li>
</ul>

2. CSS Code
The key points are:
- Specify the
<li>element toposition:relativeand apply a bottom border style. - Use
position:absolutewith negativebottomvalue to shift the<strong>and<em>element below the border. - Remember: use relative value (em) to control the padding space.
.menu {
width: 500px;
list-style: none;
margin: 0 0 2em;
padding: 0;
font: 150%/100% Arial, Helvetica, sans-serif;
}
.menu li {
clear: both;
margin: 0;
padding: 0 0 1.8em 0;
position: relative;
border-bottom: dotted 2px #999;
}
.menu strong {
background: #fff;
padding: 0 10px 0 0;
font-weight: normal;
position: absolute;
bottom: -.3em;
left: 0;
}
.menu em {
background: #fff;
padding: 0 0 0 5px;
font: 110%/100% Georgia, "Times New Roman", Times, serif;
position: absolute;
bottom: -.2em;
right: 0;
}
.menu sup {
font-size: 60%;
color: #666;
margin-left: 3px;
}
3. Change Border Style
You can easily change the style by editing the CSS border and padding for the <li> element.
li {
border-bottom: dashed 1px #000;
padding: 0 0 2.3em 0;
}
4. Use Image as Border (see final demos)
You can also use a background image.
li {
background: url(images/circle.gif) repeat-x left bottom;
}
5. IE6 Version (see IE6 demo)
If you are still using the old and buggie IE6 browser, you may notice the layout doesn't render properly. To fix the issue, simply add the clearfix trick to the <li> element.
/* clearfix */
.menu li:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.menu li {display: inline-block;}
/* Hides from IE-mac \*/
* html .menu li {height: 1%;}
.menu li {display: block;}
/* End hide from IE-mac */
You can achieve the same effect without absolute positioning and without setting padding to flesh out the list item.
Set the strong and em elements (which I think are used slightly inappropriately in your example) to position:relative and float the former left and the latter right. You can still shift elements using top / bottom / left / right and position:relative but there is the benefit, in this situation, that the “space” taken up by the elements before they are offset is maintained and so the list item will be equal in height to the height of the largest element. This negates the need to force the list item to have some kind of height that is divorced from the height of its child elements.
Since you have to float both child elements you need to apply the :after clearfix to the menu list items. You can achieve the same thing in IE just by setting a width, such as 100% in this example, because you only need to trigger hasLayout.
Then any additional inter list item spacing can be controlled with margins.
@ Kit
That’s because this tutorial sets the line-height of the em element at 100%. Change the line height to something like 1.2em and your numbers will not be cut off in IE.
Great example…..thanks!
Weirdly enough, I needed exactly this today. Thanks a bunch for this tut. =D
Very nice and great ideat,
Thank you ^:)^
Ha! Been looking for this like years ago, thanks!
Amazing! I can not imagine how. I want to use.
thank!
Thanks for the tutorial, Nick.
However, I agree with the commenter gareth hunt, that, in terms of semantics, the strong and em tags are used incorrectly. The same can be said for the sup tag.
Remember folks, we’re trying to write better code every day, and our tags should be describing the type of information, not how they should displayed (for example, just because you want the $.00 to be raised, it’s not a legitimate superscript, such as a footnote or mathematical equation.)
if you want to keep semantics just swap the tags for spans and set a class. It adds codes but you are left with semantically correct code. good tip tho.
it’s a good CSS tutorial. I do the same effect without absolute positioning.
Nice write-up on a cheeky little technique. I like it :)
Nice one! Will use for my next restaurant clients.
I did something similar for the menu on my Kamalaspa site, though a background image to recreate the dots and get around IE 6′s crash on dotted border:
http://www.kamalaspa.com/spa-salon/
But I had to use Firefox specfic hacks (eek, I know) because the right side element was always 10 pixels up… thanks for tutorial, I’ll try and rework this old guy to be more universal on your method:)
i may use it for my portfolio, to display skill level stuff..
nice tutorial though, thanks.
muito bom!!!
adorei o post :)
@matt and garret:
As of the sup tag… In some languages is common to write smaller changes (eg cents) in superscript. Though, it’s semantically correct.
Also, for strong and em – why it’s semantically incorrect? Those parts have semantic value – the name of the dish/skill/etc and the price/time/level (something to emphasise). I think using Span tags will be worse, because it doesn’t semantically distinct two pieces of information in list entry – target and the price.
BTW, nice tutorial. Thanks.
Great tutorial!
Even with IE6 trick, it fails because of the positioning. This one ( http://webdesignerwall.com/demo/menu/menu-list-ie6-version.html ) opened in IE6 shows the big values with the bottom cut. So, in Spicy Hot Roll seems 20.99 and not 29.99
If we add conditional comments ( if lt IE7 etc) and reduce the em might work, don’t?
I’ll try it and tell you later.
See you :)
Regards
RaphaelDDL.com
I was just working on a menu and was trying to come up with a better way to display it. Thanks so much for this!
Thanks for a great tutorial!