420

I have a list of elements, which are styled like this:

ul {
    list-style-type: none;
    text-align: center;
}

li {
    display: inline;
}

li:not(:last-child):after {
    content:' |';
}
<ul>
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
    <li>Four</li>
    <li>Five</li>
</ul>

Outputs One | Two | Three | Four | Five | instead of One | Two | Three | Four | Five

Anyone know how to CSS select all but the last element?

You can see the definition of the :not() selector here

diralik
  • 6,391
  • 3
  • 28
  • 52
Matt Clarkson
  • 14,106
  • 10
  • 57
  • 85

8 Answers8

475

If it's a problem with the not selector, you can set all of them and override the last one

li:after
{
  content: ' |';
}
li:last-child:after
{
  content: '';
}

or if you can use before, no need for last-child

li+li:before
{
  content: '| ';
}
imma
  • 4,912
  • 2
  • 17
  • 10
  • 15
    This is actually the only way to get it to work as far back as IE8 (sorry, no cheetos for IE7 and earlier). `li:not(:first-child):before` is a little bit too scary for the older versions of Internet Explorer to tackle. – Sandy Gifford Oct 22 '12 at 16:39
269

Every things seems correct. You might want to use the following css selector instead of what you used.

ul > li:not(:last-child)::after
Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57
Vivek
  • 4,786
  • 2
  • 18
  • 27
  • 4
    @ScottBeeson This is the best awnser for modern browser, but accepted answer work with old browsers. (I agree with you, this should be the accepted one) – Arthur Mar 14 '18 at 11:09
37

For me it work fine

&:not(:last-child){
            text-transform: uppercase;
        }
Ashad Nasim
  • 2,511
  • 21
  • 37
26

Your example as written works perfectly in Chrome 11 for me. Perhaps your browser just doesn't support the :not() selector?

You may need to use JavaScript or similar to accomplish this cross-browser. jQuery implements :not() in its selector API.

Liza Daly
  • 2,933
  • 23
  • 31
  • 9
    I solved this by doing `li:not(:first-child):before` and adding the vertical bar before. I was working with the stable version of Chrome that doesn't seem to support last-child. The Canary build does. Thanks for the answer tho. – Matt Clarkson Mar 30 '11 at 22:40
23

An example using CSS

  ul li:not(:last-child){
        border-right: 1px solid rgba(153, 151, 151, 0.75);
    }
Lorena Pita
  • 1,366
  • 1
  • 17
  • 20
11

Your sample does not work in IE for me, you have to specify Doctype header in your document to render your page in standard way in IE to use the content CSS property:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<html>

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

</html>

Second way is to use CSS 3 selectors

li:not(:last-of-type):after
{
    content:           " |";
}

But you still need to specify Doctype

And third way is to use JQuery with some script like following:

<script type="text/javascript" src="jquery-1.4.1.js"></script>
<link href="style2.css" rel="stylesheet" type="text/css">
</head>
<html>

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

<script type="text/javascript">
  $(document).ready(function () {
      $("li:not(:last)").append(" | ");
    });
</script>

Advantage of third way is that you dont have to specify doctype and jQuery will take care of compatibility.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Martin Kunc
  • 154
  • 4
-1

Remove the : before last-child and the :after and used

 ul li:not(last-child){
 content:' |';
}

Hopefully,it should work

Jaylukmann
  • 99
  • 1
  • 3
-1

Remove the : before last-child and the :after and used

ul > li:not(:last-child):after {
   border-bottom: none !important;
}
Fahimeh Ahmadi
  • 813
  • 8
  • 13