I am using JS's querySelectorAll()
to get some elements. The following selector works as I want: main > div, main > section, main > ul > li
.
I would like to remove the main >
redundancy part of that. The following works for me: main > :where(div, section), main > ul > li
.
But, I cannot figure out how to get the ul > li
complex selector portion to work inside there :where()
function. It is just ignored. The div
and section
are picked up, just like a forgiving-selector-list should.
From what I can see, div, section, ul > li
is a valid selector list.
However, in my research, I have only seen uses of :where()
or :is()
with simple selectors, maybe compound.
What am I missing?
If it matters, I am using Firefox 117.0.1
main > div,
main > section,
main > ul > li {
color: red;
}
<main>
<div>Div</div>
<section>Section</section>
<ul>
<li>List item 1</li>
<li>List item 2</li>
</ul>
</main>
:where()
for div, section
:main > :where(div, section),
main > ul > li {
color: red;
}
<main>
<div>Div</div>
<section>Section</section>
<ul>
<li>List item 1</li>
<li>List item 2</li>
</ul>
</main>
:where()
for div, section
and ul > li
:main > :where(div, section, ul > li) {
color: red;
}
<main>
<div>Div</div>
<section>Section</section>
<ul>
<li>List item 1</li>
<li>List item 2</li>
</ul>
</main>
The problem isn't to-do with using a complex-selector with :where()
and :is()
- or anything to do with them using a forgiving-selector-list; the problem is that main > :where(ul > li)
is not satisfiable.
The current (draft) specification for CSS Selectors Level 4, defines :where()
as being identical to :is()
but with a specificity of zero, so let's take a look at :is()
instead:
https://drafts.csswg.org/selectors/#matches
the [
:is()
] pseudo-class matches any element that matches any of the selectors in the list.
...therefore, main > :where(ul > li)
matches elements that simultaneously satisfy:
main
li
that is also an immediate child of ul
I would like to remove the
main >
redundancy part of that. The following works for me:main > :where(div, section), main > ul > li
The problem here is that you think that's what you ought to do. I don't see any "redundancy" in your selectors. While this might superficially look like a violation of DRY, in my opinion it is not; or summarized as: you cannot simplify your selector any further.
The snippet below demonstrates that you can use a complex-selector inside :where()
or :is()
, provided the selector is still satisfiable, in this case, by using the descendant combinator
(a space) instead of the child combinator >
, like so:
main :where(ul > li, div)
This works because an element e
that matches ul > li
can also match main e
(but not main > e
). But this selector also matches other ul > li
descendants of main
, such as List item 3 below:
ul { color: blue; }
main :where(ul > li, div) {
color: red;
}
<main>
<div>Div (red)</div>
<section>Section (black)</section>
<ul>
<li>List item 1 (red)</li>
<li>List item 2 (red)</li>
</ul>
<fieldset>
List in a fieldset
<ul>
<li>List item 3 (red)</li>
<li>List item 4 (red)</li>
</ul>
</fieldset>
</main>