Skip to content

Commit 2f3f613

Browse files
committed
[selectors-4] Specify forgiving-selector parsing, and use it in :is() and :where(). (Per WG resolution, we dont' use it in :not().) #3264
1 parent b801b2f commit 2f3f613

File tree

1 file changed

+53
-10
lines changed

1 file changed

+53
-10
lines changed

selectors-4/Overview.bs

+53-10
Original file line numberDiff line numberDiff line change
@@ -996,11 +996,6 @@ Invalid Selectors and Error Handling</h3>
996996
<li>an empty selector, i.e. one that contains no <a>compound selector</a>, is invalid.
997997
</ul>
998998

999-
ISSUE: The CSSWG indends to modify these rules such that an invalid selector
1000-
in the selector list argument of a pseudo-class like `:is()`
1001-
is simply ignored rather than invalidating the whole selector list.
1002-
See <a href="https://github.com/w3c/csswg-drafts/issues/3264">Issue 3264</a>.
1003-
1004999
Note: Consistent with CSS’s forwards-compatible parsing principle,
10051000
UAs <em>must</em> treat as <a>invalid</a>
10061001
any pseudo-classes, pseudo-elements, combinators, or other syntactic constructs
@@ -1066,8 +1061,12 @@ Selector Lists</h3>
10661061
The Matches-Any Pseudo-class: '':is()''</h3>
10671062

10681063
The matches-any pseudo-class, <dfn id='matches-pseudo'>:is()</dfn>,
1069-
is a functional pseudo-class taking a <a>selector list</a> as its argument.
1070-
It represents an element that is represented by its argument.
1064+
is a functional pseudo-class taking a <<forgiving-selector-list>> as its sole argument.
1065+
1066+
If the argument, after parsing, is an empty list,
1067+
the pseudo-class is valid but matches nothing.
1068+
Otherwise, the pseudo-class matches any element
1069+
that matches any of the selectors in the list.
10711070

10721071
Note: The specificity of the '':is()'' pseudo-class
10731072
is replaced by the specificity of its most specific argument.
@@ -1165,7 +1164,7 @@ The Specificity-adjustment Pseudo-class: '':where()''</h3>
11651164
The Specificity-adjustment pseudo-class, <dfn id="where-pseudo">:where()</dfn>,
11661165
is a functional pseudo-class
11671166
with the same syntax and functionality as '':is()''.
1168-
Unlike '':is()'', neither the '':where'' pseudo-class, nor any of its arguments
1167+
Unlike '':is()'', neither the '':where()'' pseudo-class, nor any of its arguments,
11691168
contribute to the specificity of the selector--
11701169
its specificity is always zero.
11711170

@@ -1209,7 +1208,7 @@ The Specificity-adjustment Pseudo-class: '':where()''</h3>
12091208
The Relational Pseudo-class: '':has()''</h3>
12101209

12111210
The relational pseudo-class, <dfn id='has-pseudo'>:has()</dfn>,
1212-
is a functional pseudo-class taking a <a>relative selector</a> <a lt="selector list">list</a> as an argument.
1211+
is a functional pseudo-class taking a <<forgiving-relative-selector-list>> as an argument.
12131212
It represents an element if any of the <a>relative selectors</a>,
12141213
when <a href="#absolutize">absolutized</a>
12151214
and evaluated with the element as the <a>:scope elements</a>,
@@ -3476,8 +3475,52 @@ Grammar</h2>
34763475
but these are specified on a case-by-case basis.
34773476
(For example, the <a>user action pseudo-classes</a> are allowed after any <a>pseudo-element</a>,
34783477
and the <a>tree-abiding pseudo-elements</a>
3479-
are allowed after the ''::slotted()'' pseudo-element)
3478+
are allowed after the ''::slotted()'' pseudo-element.)
3479+
3480+
<h3 id='forgiving-selector'>
3481+
<<forgiving-selector-list>> and <<forgiving-relative-selector-list>></h3>
3482+
3483+
For legacy reasons,
3484+
the general behavior of a selector list
3485+
is that if any selector in the list fails to parse
3486+
(because it uses new or UA-specific selector features, for instance),
3487+
the entire selector list becomes invalid.
3488+
This can make it hard to write CSS that uses new selectors
3489+
and still works correctly in older user agents.
3490+
3491+
The <dfn><<forgiving-selector-list>></dfn> production
3492+
instead parses each selector in the list individually,
3493+
simply ignoring ones that fail to parse,
3494+
so the remaining selectors can still be used.
3495+
3496+
Note: Style rules still use the normal, unforgiving selector list behavior.
3497+
<<forgiving-selector-list>> is used in some functions,
3498+
like '':is()'',
3499+
which are similarly generic.
3500+
Although it does have some minor implications on specificity,
3501+
simply wrapping a style rule's selector in '':is()''
3502+
effectively "upgrades" it to become forgiving.
3503+
3504+
Syntactically, <<forgiving-selector-list>> is equivalent to <code><<any-value>>?</code>.
3505+
It is then [=parsed as a forgiving selector list=]
3506+
to obtain its actual value.
3507+
3508+
<div algorithm>
3509+
To <dfn export lt="parse as a forgiving selector list|parsed as a forgiving selector list|parsing as a forgiving selector list">parse as a forgiving selector list</dfn> given an input |input|:
3510+
3511+
1. [=Parse a list=] of <<complex-selector>>s from |input|,
3512+
and let |selector list| be the result.
3513+
3514+
3. Remove all failure items from |selector list|,
3515+
and all items that are [=invalid selectors=],
3516+
then return a <<selector-list>>
3517+
representing the remaining items in |selector list|.
3518+
(This might be empty.)
3519+
</div>
34803520

3521+
<dfn><<forgiving-relative-selector-list>></dfn> is identical to <<forgiving-selector-list>>,
3522+
except it parses its components as <<relative-selector>>
3523+
rather than <<complex-selector>>.
34813524

34823525
<h2 id='api-hooks'>
34833526
API Hooks</h2>

0 commit comments

Comments
 (0)