Open annevk opened 6 years ago
Isn't such string inside :not()
parsed as a type selector which is invalid because it doesn't match the <ident-token>
grammar?
As far as I can tell https://drafts.csswg.org/selectors/#typedef-pseudo-class-selector accepts any value for all functional pseudo-classes. It does seem like a more restrictive grammar is then applied and ends up rejecting the selector, but it's not clear to me how that is defined.
The definition of the :not()
pseudo-class says that it takes a selector list as an argument. So I suppose that anything inside the brackets is parsed as a selector list (consisting of one invalid simple selector in this case). I guess this is one of the "more specific syntactic constraints" which the first note after the formal grammar description in the section 17 warns about.
Yeah, like individual properties, individual pseudo-classes and pseudo-elements define their grammars at the point of definition. The panoply of pseudo-class grammars is not captured in the generic selector grammar, just like the panoply of property grammars aren't captured in the Syntax spec.
Sure, but how does that follow from https://drafts.csswg.org/selectors/#invalid (or the "parse a selector" algorithm)? At some point you actually need to do a lookup of that specific grammar and apply it.
(Notes are non-normative so when you try to determine the requirements you have to pretend they're not there.)
It follows from the bullet point:
a selector containing an invalid simple selector, an invalid combinator or an invalid token is invalid.
Each simple selector defines its grammar.
(Notes are non-normative so when you try to determine the requirements you have to pretend they're not there.)
Indeed, that note is just a reminder of requirements elsewhere. It's not relevant to your question.
I see. Nothing in https://drafts.csswg.org/selectors/#negation states what makes that simple selector invalid though (nothing in the section on simple selectors or pseudo-classes does either). It all hangs rather loosely together, without much formal rigor.
@annevk
The negation pseudo-class, :not(), is a functional pseudo-class taking a selector list as an argument.
A list of simple/compound/complex selectors is a comma-separated list of simple, compound, or complex selectors. This is also called just a selector list when the type is either unimportant or specified in the surrounding prose; if the type is important and unspecified, it defaults to meaning a list of complex selectors.
A complex selector is a sequence of one or more compound selectors separated by combinators.
A compound selector is a sequence of simple selectors that are not separated by a combinator
A simple selector is a single condition on an element. A type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class is a simple selector.
1
and 1px
do not match the grammars for type selectors, universal selectors, attribute selectors, class selectors, ID selectors, or pseudo-classes. Therefore they are not valid simple selectors, therefore not valid compound selectors, therefore not valid complex selectors, therefore not a valid selector list, therefore not a valid argument to :not()
, therefore it is a parsing error in that selector (being a token which is not allowed at that parsing point) and :not()
is invalid and any selector containing it is also invalid.
Tweaked the parenthetical wording in https://drafts.csswg.org/selectors-4/#invalid to not imply that the Grammar section is the only arbiter of validity.
@annevk Let me know if something remains unclear. Afaict, the spec defines the syntax with sufficient rigor, it just happens to be partly in English rather than completely subsumed into a grammar definition syntax.
Thanks for the help! I'm not a huge fan of this style of specifying things (as it requires the reader to do a lot of digging), but it does seem defined.
What remains unclear is why the note in that #invalid section has a normative requirement.
Also:
a selector list containing an invalid selector is invalid.
A forgiving selector list should remain valid when it becomes empty after invalid selectors are removed: this is explicitly defined for :is()
(and implicitly for :where()
) but not for :has()
and :nth-*-child()
.
It would be clearer to define it once in the error handling list, imo.
EDIT: parsing of :has()
and :nth-*-child()
argument is now unforgiving but my suggestion remains.
I could be missing something, but it's not clear to me how https://drafts.csswg.org/selectors/#invalid applies to
:not(1)
ornot(1px)
or some such.