0

Say I have a ul as such:

<ul>
   <li class="good"></li>
   <li class="bad"></li>
   <li class="bad"></li>
   <li class="bad"></li>
   <li class="bad"></li>
   <li class="good"></li>
   <li class="bad"></li>
   <li class="bad"></li>
   <li class="bad"></li>
   <li class="bad"></li>
   <li class="good"></li>
   <li class="bad"></li>
   <li class="bad"></li>
</ul>

I want to select all the child of elements of ul that are less than the eighth child (so the first 7) and don't have the class bad.

I want to do something like querySelectorAll('ul li:not(:nth-child(n+3)) li:not(.bad)') Is there a way I can do this?

yalpsid eman
  • 3,064
  • 6
  • 45
  • 71
  • 2
    Please edit the question to include text in the `li`s saying whether they should or should not be in the result you want. (Also: Your `ul` doesn't have the class `unstyled`.) – T.J. Crowder Dec 17 '19 at 16:31

2 Answers2

0

I don't think you can do the "less than 8th" with just CSS, but you can convert the NodeList from querySelectorAll into an array and grab just the first seven via .slice(0, 7), then filter out the ones with the class you don't want (bad in your sample data I think):

const list = [...document.querySelectorAll("ul.unstyled li")]
                .slice(0, 7)
                .filter(li => !li.classList.contains("bad"));

Live Example:

const list = [...document.querySelectorAll("ul.unstyled li")].slice(0, 7).filter(li => !li.classList.contains("bad"));

for (const li of list) {
    console.log(li.textContent);
}
<ul class="unstyled">
   <li class="good">0</li>
   <li class="bad">1</li>
   <li class="bad">2</li>
   <li class="bad">3</li>
   <li class="bad">4</li>
   <li class="good">5</li>
   <li class="bad">6</li>
   <li class="bad">7</li>
   <li class="bad">8</li>
   <li class="bad">9</li>
   <li class="good">10</li>
   <li class="bad">11</li>
   <li class="bad">12</li>
</ul>

The above assumes that NodeList is iterable on your browser, as it is on most. If it isn't, but your environment supports ES2015+, you can easily polyfill it using my answer here. Alternatively, use Array.prototype.slice directly as in this ES5 example:

var list = Array.prototype.slice.call(
                document.querySelectorAll("ul.unstyled li"),
                0, 7
            ).filter(function(li) { return !li.classList.contains("bad"); });
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

This worked for me:

document.querySelectorAll("ul li:not(:nth-child(n+8)):not(.bad)");