-
Notifications
You must be signed in to change notification settings - Fork 23
Implement :matches() #48
Description
Relevant spec: https://drafts.csswg.org/selectors-4/#matches
What makes this non-trivial is the handling of specificity: https://drafts.csswg.org/selectors-4/#specificity-rules
For example, div :matches(.foo, #bar) is equivalent div .foo, div #bar. The latter is a selector list that contains two selectors. (See terminology.) In Selectors level 3, selectors have an intrinsic specificity (here (0, 1, 1) and (1, 0, 1), respectively) but selector lists don’t. This is a consequence of the principle that these two bits of CSS are equivalent:
div .foo, div #bar { color: blue }div .foo { color: blue }
div #bar { color: blue }Going back to div :matches(.foo, #bar), preserving the equivalence means that, in Selectors level 4, the specificity is not intrinsic to (all) selectors anymore: the specificity of :matches() depends on which of its arguments actually matches for a given element.
I know of two ways to implement this:
-
Expand at parse time a selector list that contains
:matches()to the equivalent, longer selector list that doesn’t. This works without changing much code, but it cause a combinatorial explosion of the size of selectors with more than one:matches()pseudo-class. For example (from the user-agent stylesheet):matches(dir, menu, ol, ul) :matches(dir, menu, ol, ul) :matches(dir, menu, ul) { list-style-type: square; }
… this expands to 64 alternatives. The run-time cost of matching this may be prohibitive
-
Change our matching code so that specificity is not determined at parse-time but is a result of matching. (A return value of
Option<Specificity>instead ofboolfor a given(element, selector)set of arguments.) This might make more difficult plans to JIT-compile selectors or match them on the GPU