CSS Shorthand for all but the last item

Written on March 14, 2015
  • Targeting a child element is easy: :last-of-type
  • Targeting all but one element is pretty easy, too: :not
  • Chain those together and what do you get? One line of code and less markup in your html!

There are several different approaches to get this:

But, what’s the best way of going about that?

The dirty HTML / redundant CSS way

Add a class to the last child element:


<ul class="section-wrap">
  <li class= "navitem"><a href="#">Home
  <li class= "navitem"><a href="#">About
  <li class= "navitem"><a href="#">Thoughts
  <li class= "navitem last-navitem"><a href="#">Projects
</ul>

.navitem { margin-right: 30px; }
.last-navitem { margin-right: 0; }

Or…


.navitem { margin-right: 30px; }
.navitem.last-navitem { margin-right: 0; }

The Good:

  • This is the fastest way to render your code

The Bad

  • You’ll either need to ensure that .last-navitem never gets moved before .navitem in the css or you’re going to need to get more specific:
    • .navitem.last-navitem: (not good - we’re starting to run into specificity differences)
    • last-navitem { margin-right: 0!important; }: Really? I hope you’re not using !important on any of your code
  • Styles should be handled outside of the html (quoting this bit from birjolaxew)
    • html is a structural language
    • The last item is already structured as the last item, simply by being the last item
    • Adding a class to it is redundant and frankly ugly

The redundant CSS way


<ul class="section-wrap">
  <li class= "navitem"><a href="#">Home
  <li class= "navitem"><a href="#">About
  <li class= "navitem"><a href="#">Thoughts
  <li class= "navitem"><a href="#">Projects
</ul>

.navitem { margin-right: 30px; }
.navitem:last-of-type { margin-right: 0; }

The Good:

  • You’re not going to lose that much on performance compared to the first example
  • Keeps your styles outside of your html

The Bad:

  • You define .navitem’s styles twice, which causes the browser to repaint (maybe don’t put this on a tag used 1000 times throughout the site)

The shorthand


<ul class="section-wrap">
  <li class= "navitem"><a href="#">Home
  <li class= "navitem"><a href="#">About
  <li class= "navitem"><a href="#">Thoughts
  <li class= "navitem"><a href="#">Projects
</ul>

.navitem:not(:last-of-type) { margin-right: 30px; }

The Good:

  • One line of css and no html bloat!

The Bad:

  • You define .navitem’s styles twice, which causes the browser to repaint (maybe don’t put this on a tag used 1000 times throughout the site) (see conclusion for more details on this one)

Conclusion

At the moment, I’m not sure if there is any difference in performance hit between the second example and this one. If you have any insight, “prey,” do tell!

Here’s the codepen for the shorthand.