'Is there any way to specify a CSS shorthand for "all elements except the first/last"?

Very often, it's natural to need to specify a CSS style for all elements except the first (or the last). For example, when styling paragraphs, you wish to add a bottom margin to every element except the last one (or similarly, a top margin to every element except the first one).

Is there any way to do that that's :

  • more concise than defining p {...} and then p:first-child {...}?
  • more straightforward and intuitive than p:nth-child(-n+1)?

If there is not, do you know of any attempt at adding it?



Solution 1:[1]

If IE7-8 support is not needed you can use the :not() CSS selector, like:

p:not(:first-child) {
    ...
}

But if you need to support IE7+, which may still be the case there is a little trick you can use and usually gets you fairly far. A lesser known fact is that the :first-child psuedo selector actually works in IE7+ (not :last-child though) as are some other css selectors and this makes stuff like adding vertical margins in a horizontally floated layout possible.

Imagine this html:

<ul>
    <li>Item #1</li>
    <li>Item #2</li>
    <li>Item #3</li>
    <li>Item #4</li>
</ul>

And this as some CSS:

/* General reset */
ul, li { list-type: none; margin: 0; padding: 0; }
/* Make horizontal */
ul > li { float: left; }

So now all list items are horizontally next to each other, and now we want to add a margin in BETWEEN all items but not on the right or left side, we can do this in css:

/* General reset */
ul, li { list-type: none; margin: 0; padding: 0; }
/* Make horizontal */
ul > li { float: left; margin-left: 10px; }
ul > li:first-child { margin-left: 0; }

This usually covers 95% of the cases where I want something unique, then the rest of the 'forgotten' selectors cover another few percent, after that you need to add some classes which usually isn't much of a bottleneck anyway in the backend of the page.

Solution 2:[2]

Well, you could do:

p:not(:first-child) {...}

But only the most recent browsers support the :not psuedo-class.

Other than that, no. Your best option is to specify a style for all and then override it for the first/last.

Solution 3:[3]

I would suggest to use first-of-type:

p:not(:first-of-type) { ... }

Browser support (caniuse)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Top-Master
Solution 2 Niet the Dark Absol
Solution 3