Naftali
Naftali

Reputation: 146302

How do I target the last N sibling elements only when there are Y siblings in CSS?

Is it possible to target the last N sibling elements when there are Y siblings?

For example I have list of items, if and only if there are exactly 8, 11, 14... etc sibling elements I want the last two to look different (so 8 + 3n).

If there is any other amount of children I want them all to look the same.

Upvotes: 3

Views: 200

Answers (3)

BoltClock
BoltClock

Reputation: 723538

The easiest way by far is to target each of the 2 elements you want to style with its own set of pseudo-classes.

The last child, as you state, is represented by 3n+8 (8, 11, 14...). It then follows that the penultimate child is 3n+7 (7, 10, 13...).

li:nth-last-child(1):nth-child(3n+8),
li:nth-last-child(2):nth-child(3n+7) {
  color: red;
}

ul { counter-reset: item; list-style-type: none; }
li { display: inline; padding: 0.25em; }
li::before { content: counter(item); counter-increment: item; }
<ul><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li><li><li><li><li></ul>

You can also do this with one complex selector using the technique from Can CSS detect the number of children an element has?, substituting 3n+8 for the :nth-last-child() argument, and using an additional :nth-last-child(-n+2) to target the last two elements with one pseudo-class:

li:first-child:nth-last-child(3n+8) ~ li:nth-last-child(-n+2) {
  color: red;
}

ul { counter-reset: item; list-style-type: none; }
li { display: inline; padding: 0.25em; }
li::before { content: counter(item); counter-increment: item; }
<ul><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li><li><li><li></ul>
<ul><li><li><li><li><li><li><li><li><li><li><li><li><li><li></ul>

Upvotes: 8

Rounin
Rounin

Reputation: 29453

Is it possible to target the last N sibling elements when there are Y siblings?

Yes, you can chain pseudo-classes so that they have to match a count from the beginning and a count from the end:

ol li:nth-of-type(3n + 8):nth-last-of-type(1),
ol li:nth-of-type(3n + 7):nth-last-of-type(2) {
color: rgb(255,0,0);
}

Example:

ol {
float:left;
width:80px;
}

ol li:nth-of-type(3n + 8):nth-last-of-type(1),
ol li:nth-of-type(3n + 7):nth-last-of-type(2) {
color: rgb(255,0,0);
}
<ol>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
</ol>

<ol>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
</ol>

<ol>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
</ol>

<ol>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
</ol>

<ol>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
</ol>

<ol>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
</ol>

<ol>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
</ol>

<ol>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
<li>Element</li>
</ol>

Upvotes: 0

Tom B.
Tom B.

Reputation: 2962

Based on

If and only if there are 8 elements I want the last two to look different.

You'll get this:

li:nth-child(7):nth-last-child(2),
li:nth-child(8):nth-last-child(1) {
  color: red;
}
Will colorize 7 and 8
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
</ul>
Will colorize nothing since it has more then 8 elements
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
</ul>

Upvotes: 3

Related Questions