12

In CSS, is it possible to recursively select all :last-child from body?

Given this markup:

<body>
  <div id="_1">
    <div id="_2"></div>
  </div>
  <div id="_3">
    <div id="_4">
      <div id="_5"></div>
      <div id="_6"></div>
    </div>
  </div>
</body>

I am looking for div no. 3, 4 and 6

Another way to put it is this:

body > :last-child,
body > :last-child > :last-child,
body > :last-child > :last-child > :last-child,
body > :last-child > :last-child > :last-child > :last-child {
  /* My stuff here */
}

But obviously this is not a good approach.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Lasse Skindstad Ebert
  • 3,370
  • 2
  • 29
  • 28
  • If one of the following were solved, we would be able to solve this one as well: https://stackoverflow.com/questions/10227375/css-not-selectors-and-selecting-descendants | https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector by checking that there is no non-last parent. – Ciro Santilli OurBigBook.com Apr 28 '20 at 07:02

3 Answers3

7

No, unfortunately that's just about the only way to do it without modifying the HTML.

There has been at least one request for recursive versions of the :first-child and :last-child pseudo-classes, but it doesn't seem to have gained much favor. Notice it suggests nesting and repeating the pseudo-classes in the same way as in your question:

Currently, AFAIK, we can only match children up to some exact nesting level known in advance (3 in the example below):

.container > :first-child,
.container > :first-child > :first-child,
.container > :first-child > :first-child > :first-child {}

We cannot use just :first-child context selector since it would also select first children of blocks that are not first children themselves.

So we need a sort of recursive selector that matches not just first of last child, but recursively matches all first-most and last-most elements regardless of their nesting level.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
2
body :last-child {
    color:red;
}
body :not(:last-child) :last-child {
    color:initial;
}

Any last-child element that's a descendant of one that's not a last-child will have the change reversed.

Andy
  • 1,264
  • 1
  • 10
  • 16
0

No need to chain all the way. It would be simply like this

div:last-child {
   /* Your GREAT css */
}

Demo

Update: On that case, give the div2 a typical class and use :not() to push out of the selection

div:last-child:not(.nolist) {
    border: 1px solid red;
}

Demo

Starx
  • 77,474
  • 47
  • 185
  • 261