399
votes

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

8
This behaviour seems to be a bug in Chrome 10. It works for me in Firefox 3.5.duri
Actually just ran the snippet in 2018 with latest Chrome and worked as expected.atoth

8 Answers

459
votes

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: '| ';
}
256
votes

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

ul > li:not(:last-child):after
29
votes

For me it work fine

&:not(:last-child){
            text-transform: uppercase;
        }
26
votes

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.

20
votes

An example using CSS

  ul li:not(:last-child){
        border-right: 1px solid rgba(153, 151, 151, 0.75);
    }
11
votes

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.

1
votes

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

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

Hopefully,it should work

-3
votes

You can try this, I know is not the answers you are looking for but the concept is the same.

Where you are setting the styles for all the children and then removing it from the last child.

Code Snippet

li
  margin-right: 10px

  &:last-child
    margin-right: 0

Image

enter image description here