115

I need to add separators between elements of navigation. Separators are images.

Separators between elements.

My HTML structure is like: ol > li > a > img.

Here I come to two possible solutions:

  1. To add more li tags for separation (boo!),
  2. Include separator in image of each element (this is better, but it makes possibility that user may click on, example, "Home", but get to "Services", because they are one behind the other and user may accidentally click on separator that belongs to "Services");

What to do?

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
daGrevis
  • 21,014
  • 37
  • 100
  • 139

9 Answers9

141

If there isn't a pressing need to use images for the separators, you could do this with pure CSS.

nav li + li:before{
    content: " | ";
    padding: 0 10px;
}

This puts a bar between each list item, just as the image in the original question described. But since we're using the adjacent selectors, it doesn't put the bar before the first element. And since we're using the :before pseudo selector, it doesn't put one at the end.

jrue
  • 2,522
  • 4
  • 19
  • 25
  • Wow! This is exactly what I needed for my footer menu. Of course with some additional CSS. – Vladimir Feb 01 '16 at 21:18
  • Technically you could still use an image, but base64 encode it and store the image inline. https://css-tricks.com/data-uris/ – commadelimited May 13 '16 at 16:31
  • @jrue is het also possible to vertically change the positioning of the separators? It isn't responding to a top padding/margin. – Floris Nov 21 '17 at 14:07
66

Simply use the separator image as a background image on the li.

To get it to only appear in between list items, position the image to the left of the li, but not on the first one.

For example:

#nav li + li {
    background:url('seperator.gif') no-repeat top left;
    padding-left: 10px
}

This CSS adds the image to every list item that follows another list item - in other words all of them but the first.

NB. Be aware the adjacent selector (li + li) doesn't work in IE6, so you will have to just add the background image to the conventional li (with a conditional stylesheet) and perhaps apply a negative margin to one of the edges.

ajcw
  • 23,604
  • 6
  • 30
  • 47
  • 2
    Using the `:before` pseudo selector prevents it from appearing after the last element. – jrue Dec 21 '12 at 03:06
  • 3
    Nice solution -works like a charm -IE6 support? Who cares! :) If we all stop supporting legacy browsers than perhaps we will force people to stop using them. – Jordan Jul 06 '13 at 06:01
  • 1
    Works like a chram with a `border-left` to draw a vertical line between items. – Richard-Degenne Feb 18 '19 at 16:18
6

The other solution are OK, but there is no need to add separator at the very last if using :after or at the very beginning if using :before.

SO:

case :after

.link:after {
  content: '|';
  padding: 0 1rem;
}

.link:last-child:after {
  content: '';
}

case :before

.link:before {
  content: '|';
  padding: 0 1rem;
}

.link:first-child:before {
  content: '';
}
T04435
  • 12,507
  • 5
  • 54
  • 54
5

To get the separator vertically centered relative to the menu text,

.menustyle li + li:before {
  content: ' | ';
  padding: 0;
  position: relative;
  top: -2px;
}
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
user7149870
  • 51
  • 1
  • 1
3

You can add one li element where you want to add divider

<ul>
    <li> your content </li>
    <li class="divider-vertical-second-menu"></li>
    <li> NExt content </li>
    <li class="divider-vertical-second-menu"></li>
    <li> last item </li>
</ul>

In CSS you can Add following code.

.divider-vertical-second-menu{
   height: 40px;
   width: 1px;
   margin: 0 5px;
   overflow: hidden;
   background-color: #DDD;
   border-right: 2px solid #FFF;
}

This will increase you speed of execution as it will not load any image. just test it out.. :)

Rajiv Pingale
  • 995
  • 9
  • 27
  • can you please explain how? But there always other way... CSS3 : We can add get Nth Element and add Divider to it. – Rajiv Pingale Mar 11 '15 at 09:55
  • 1
    Drat, some mess I got myself into. I just spent 30 minutes rooting around in standards documents, RWD pamphlets, and even tried out different screen readers to prove my point. However, at least the screen readers are clever enough to NOT READ OUT LOUD empty bullets (nor enumerate absent options when using @ol@ instead of @ul@). So I can just point out that the use of @li@ here is in the same category as using a table to achieve column layout. – Volker Stolz Mar 11 '15 at 14:39
2

For those using Sass, I have written a mixin for this purpose:

@mixin addSeparator($element, $separator, $padding) {
    #{$element+'+'+$element}:before {
        content: $separator;
        padding: 0 $padding;
    }
}

Example:

@include addSeparator('li', '|', 1em);

Which will give you this:

li+li:before {
  content: "|";
  padding: 0 1em;
}
d4nyll
  • 11,811
  • 6
  • 54
  • 68
  • This is not showing the '|' for some reason? Any reason why not? – James111 May 04 '15 at 00:02
  • Dont worry I figured out how to do it. I also had to add an :after to the last-child to make the content of the child that doesn't need a seperator = content: "" – James111 May 05 '15 at 05:54
2

I believe the best solution for this, is what I use, and that is a natural css border:

border-right:1px solid;

You might need to take care of padding like:

padding-left: 5px;
padding-right: 5px;

Finally, if you don't want the last li to have that seperating border, give it's last-child "none" in "border-right" like this:

li:last-child{
  border-right:none;
}

Good luck :)

Avi
  • 111
  • 1
  • 3
2

Add the separator to the li background and make sure the link doesn't expand to cover the separator, which means the separator won't be click-able.

Soufiane Hassou
  • 17,257
  • 2
  • 39
  • 75
1

Put it in as a background on the list element:

<ul id="nav">
    <li><a><img /></a></li>
    ...
    <li><a><img /></a></li>
</ul>

#nav li{background: url(/images/separator.gif) no-repeat left; padding-left:20px;} 
/* left padding creates a gap between links */

Next, I recommend a different markup for accessibility:
Rather than embedding the images inline, put text in as text, surround each with a span, apply the image as a background the the , and then hide the text with display:none -- this gives much more styling flexibilty, and allows you to use tiling with a 1px wide bg image, saves bandwidth, and you can embed it in a CSS sprite, which saves HTTP calls:

HTML:

<ul id="nav">
    <li><a><span>link text</span></a></li>
    ...
    <li><a><span>link text</span></a></li>
</ul

CSS:

#nav li{background: url(/images/separator.gif) no-repeat left; padding-left:20px;} 
#nav a{background: url(/images/nav-bg.gif) repeat-x;}
#nav a span{display:none;}

UPDATE OK, I see others got similar answer in before me -- and I note that John also includes a means for keeping the separator from appearing before the first element, by using the li + li selector -- which means any li coming after another li.

Faust
  • 15,130
  • 9
  • 54
  • 111