Quantity Queries: Targeting elements by number

Back

  • 9.0+
  • 4.0+
  • 3.5+
  • 3.2+
  • 9.5+

Ever wanted to target a group of elements, and style them differently according to the amount present? Possibly not, and if you have, you’ve probably had the foresight to add a class to identify them properly. I, on the other hand, have wanted to, and choose not to have that foresight.

Interestingly, a less used selector makes this possible, *:nth-last-of-type. With this and a bit of clever structure to your CSS you can style elements to your hearts content.

Firstly we start out by styling the appearance when only one element is there. We’re going to play with paragraphs.

/* One */
p {
    background: lightblue;
}

Now using p:nth-last-of-type, we’ll go ahead a pick a style for when there’s two paragraphs.

/* Two */
p:nth-last-of-type(2), p:nth-last-of-type(2) ~ p {
    background: lightpink;
}

What’s happening? We’re targeting the second to last paragraph, (p:nth-last-of-type(2)), which, in the case of just two paragraphs is the first one, then using the same selector, we’re targeting any paragraphs that follow (p:nth-last-of-type(2) ~ p).

Being a more specific and later declared rule than p, in the case of two paragraphs, this rule has precedence.

Now what if we want more?

/* Three */
p:nth-last-of-type(3), p:nth-last-of-type(3) ~ p {
    background: red;
}

Now, similarly, we target the 3rd to last paragraph (p:nth-last-of-type(3)), which in the case of three paragraphs, becomes the first. Then similarly we target any paragraphs following.

Awesome

Now keep going till you’ve styled everything you expect. But what happens, when an author adds one too many paragraphs?

What’s happening? Well we’re targeting the last three with our p:nth-last-of-type(3), p:nth-last-of-type(3) ~ p rule, but not our first, which is still being targeted by our base p rule.

Instead, what we really need to be doing is saying we want to target 3 paragraphs and above. Changing our code slightly we get...

/* Only one :D */
p {
    background: lightblue;
}

/* 2+ p */
p:nth-last-of-type(n+2), p:nth-last-of-type(n+2) ~ p {
    background: lightpink;
}

/* 3+ p */
p:nth-last-of-type(n+3), p:nth-last-of-type(n+3) ~ p {
    background: red;
}

Using n+3, instead, we’re saying we want to target the 3rd to last paragraph plus n. Which CSS interprets as 0 right up to infinity.

Magic