2

I have a list of elements under the same container. some of them has class A, other has class B. I'm looking for a CSS selector to select the first A element in a group of A and the first B element in a group of B.

Example:

    <style>
    .A { background: red; }
    .B { background: blue; }
    </style>
    <ul class="list">
      <li class="item A">AAA</li><!-- I want to select this -->
      <li class="item A">aaa</li>
      <li class="item A">aaa</li>
      <li class="item B">BBB</li><!-- I want to select this -->
      <li class="item B">bbb</li>
      <li class="item B">bbb</li>
      <li class="item A">AAA</li><!-- I want to select this -->
      <li class="item A">aaa</li>
      <li class="item A">aaa</li>
    </ul>

Notice that using the pseudo selector :first-of-type will not work, becuase it will select the first element of type without group relation.

Also trying to use :first-child will not work ether, since it will select only the first A element, and will not select the first B element, also it will not select the first A element in the 2nd group.

Note

I don't believe this is a duplicate of "CSS selector for first element with class".

Community
  • 1
  • 1
Gil Epshtain
  • 8,670
  • 7
  • 63
  • 89
  • 3
    @Rob, I think you don't understand my question. No `first-child` will **not** work! I'm not trying to select the first child, I looking for a selector to select the first element in a group of elements. In the example you can see that I want to select the first B item. using `first-child` will not work! – Gil Epshtain Dec 15 '19 at 13:32
  • `first-child` will only select first child of `ul` element. – Yousaf Dec 15 '19 at 13:32
  • You are right. I misunderstood. – Rob Dec 15 '19 at 13:33

2 Answers2

8

To select first child of the ul element, you can use :first-child pseudo-class.

To select the first element in each group, you can use adjacent sibling selector.

.A + .B will select any element with class B that immediately follows an element with class A. Similarly .B + .A will select any element with class A that immediately follows an element with class B

.A { background: red; }
.B { background: blue; }

.A:first-child,
.B + .A,
.A + .B {
  background: yellow;
}
<ul class="list">
  <li class="item A">AAA</li><!-- I want to select this -->
  <li class="item A">AAA</li>
  <li class="item A">AAA</li>
  <li class="item B">BBB</li><!-- I want to select this -->
  <li class="item B">BBB</li>
  <li class="item B">BBB</li>
  <li class="item A">AAA</li><!-- I want to select this -->
  <li class="item A">AAA</li>
  <li class="item A">AAA</li>
</ul>
Yousaf
  • 27,861
  • 6
  • 44
  • 69
0

In case you didn't know what's each class name (for example, when scraping) you could use JS to find groups that match your criteria:

let list = document.querySelector('.list');


let filtered = [...list.children].filter((item) => {
  let previous = item.previousElementSibling;
  return !previous || [...previous.classList].join('.') !== [...item.classList].join('.');
});

console.log(filtered);
.A {
  background: red;
}

.B {
  background: blue;
}
<ul class="list">
  <li class="item A">First AAA</li>
  <!-- I want to select this -->
  <li class="item A">AAA</li>
  <li class="item A">AAA</li>
  <li class="item B">First BBB</li>
  <!-- I want to select this -->
  <li class="item B">BBB</li>
  <li class="item B">BBB</li>
  <li class="item A">Second AAA</li>
  <!-- I want to select this -->
  <li class="item A">AAA</li>
  <li class="item A">AAA</li>
</ul>

You could also restrict your criteria to groups of elements that share their tagName.

ffflabs
  • 17,166
  • 5
  • 51
  • 77