2

I'm trying to create separators using CSS, for keeping it semantic, and removing styles from content.

However, I wanted to have a border bottom below each <li> item. The :before selector however, extends the width of the <li> element, and it is creating an inconsistent border.

I've tried answers from Separators For Navigation, which uses a similar approach as mine, and gives the same problems.

This is my navigation (tab-based) below

<nav class="innerNav">
    <ul>
        <li>One </li>
        <li>Two</li>
        <li>Three</li>
        <li>Four</li>
    </ul>
</nav>

and my CSS

.innerNav li {
    display: inline-block;
    border-bottom: 3px solid red;
}

.innerNav li:before {
    content: "|";
    display: inline-block;
    color: blue;
    border: 0;
    padding-right: 10px;
}

.innerNav li:first-child:before {
    display: none;
}

Here is a fiddle : http://jsfiddle.net/XFd6D/

Community
  • 1
  • 1
Aaditi Sharma
  • 766
  • 2
  • 9
  • 20

2 Answers2

2

Though you are using :before pseudo which generates the content virtually, still it is counted in the element, and hence your element extends.

Inorder to fix that, use margin-left for the li to space them up first, and then, use position: absolute; for the pseudo content and then use left: -8px; to position it correctly.

Make sure you use position: relative; for the li elements.

Demo

.innerNav li {
    display: inline-block;
    border-bottom: 3px solid red;
    margin-left: 10px;
    position: relative;
}

.innerNav li:before {
    content: "|";
    position: absolute;
    left: -8px;
    color: blue;
    border: 0;
    padding-right: 10px;
}

.innerNav li:first-child:before {
    display: none;
}

The other way you can do is to encapsulate the text of the li in a span element, and than assign border-bottom to span element rather than using it for an li

Using span

Demo

Change your DOM like

<ul>
    <li><span>One</span> </li>
    <li><span>Two</span></li>
    <li><span>Three</span></li>
    <li><span>Four</span></li>
</ul>

And associated CSS to...

.innerNav li {
    display: inline-block;
}

.innerNav li span {
    border-bottom: 3px solid red;
}

.innerNav li:before {
    content: "|";
    display: inline-block;
    color: blue;
    border: 0;
    padding-right: 10px;
    padding-left: 10px;
}

.innerNav li:first-child:before {
    display: none;
}
Mr. Alien
  • 153,751
  • 34
  • 298
  • 278
1

This should work with IE8 and higher. Kind of like the approach of Mr. Alien, but a bit shorter and with a border instead of using a pipe.

.innerNav li {
    display: inline-block;
    border-bottom: 3px solid red;
    margin-right: 1em;
    position: relative;
}

.innerNav li + li:before {
    border-left: 1px solid blue;
    content:"";
    display: block;
    height: 100%;
    position: absolute;
    left: -0.5em;
    top: 0;
}

Problem could be whitespace between your <li>, here more information about that.

chrona
  • 1,853
  • 14
  • 24
  • Thank you for the answer :) I preferred Mr. Alien's second approach, since I don't have to do a `position` modifications to achieve it. – Aaditi Sharma Jan 29 '14 at 09:23