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

Go To StackoverFlow.com

45

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?

2012-04-05 17:40
by julien_c
I think the more common solution is to apply styles to everything then remove the undesired ones by selecting the first and last to do so - kinakuta 2012-04-05 17:43
Use the :not selector: http://jsfiddle.net/FGfmj - Rob W 2012-04-05 17:43


87

For all p elements except the first child, use either one of these (the second one is better-supported):

p:not(:first-child)
p:first-child ~ p

For all p elements except the last child:

p:not(:last-child)

For all p elements except the first and the last children:

p:not(:first-child):not(:last-child)

As usual, CSS3's :not() and :last-child aren't supported until IE9+ and relatively new versions of other browsers. You're not going to reach very far in terms of browser support (IE8 and older) unless you add classes to your first and last children, using JavaScript or otherwise.

Remember that vertical margins collapse between in-flow paragraphs and their ancestor(s), so unless you want to zero out the margins of the container element for these paragraphs as well, you shouldn't need to zero out the margins of the first and last p elements specifically. Here's a fiddle to illustrate.

2012-04-05 17:43
by BoltClock
I've been writing CSS for 8 years and I didn't know about collapsing margins. CSS is really not as predictable and intuitive as it seems -- it's very tough to master! Thanks - julien_c 2012-04-05 18:12
"All p elements except the first child" can be shortened with p + pSimon 2013-09-05 16:07
@Simon: That assumes that the only children in the parent are p elements, and fails when you have, say, a blockquote or some other element between the p elements. (One might also want to substitute :*-of-type for :*-child for the same reason. - BoltClock 2016-05-03 16:55
Late to the party, but stuff like this: .footer__link a:not(:first-child) { ... } works great - thvs86 2017-12-24 15:39


3

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.

2012-04-05 17:42
by Niet the Dark Absol


3

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

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.

2012-04-05 18:17
by sg3s


2

I would suggest to use first-of-type:

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

Browser support (caniuse)

2014-04-25 11:12
by David Morales
Ads