w3c/csswg-drafts

[selectors] Functional pseudo-class like :matches() with 0 specificity

LeaVerou opened this issue ยท 50 comments

The problem

Sometimes, specificity is a blessing. However, more often than not, it gets in the way, and authors have to resort to hacks in order to artificially adjust specificity, such as repeating classes (.foo.foo.foo), turning id selectors to attribute selectors ([id=foo] instead of #foo), or adding pointless :not()s (e.g. .foo:not(.enough):not(.specificity)).

A common example where specificity goes against author intent is :not(). The default specificity rules on :not() are almost never helpful. One often includes lots of filters, one after the other, but that increases specificity and makes these rules hard to override. E.g. good luck overriding div:not(#foo):not(#bar):not(#baz) in a sane way, even though this selector is essentially as general as div minus three specific divs.

In the last few years, it has even become common to avoid selector logic altogether, just to avoid specificity woes. This is basically what conventions like BEM are all about: turning combinators and pseudo-classes into a single class selector so that every selector has the same specificity and the cascade only goes top to bottom. For example, authors would write .form__input--disabled instead of form input[disabled].

Specificity becomes an even bigger problem when authoring UI libraries, where you want your styles to be easy to override by the end author without them having to keep up with your stylesheet, but you still want to provide sensible defaults. The default Mavo stylesheet has many good examples of this. It's a stylesheet that's meant to be easy to override, and in practice, authors have to artificially increase specificity of their rules to override it because I had to be very conservative in what is styled so the selectors have to be very specific. However, being specific doesn't always mean they are high priority.

All in all, specificity is a heuristic. It's assuming that it can deduce rule priority from the selection logic, but the selector is not really expressing priority, it's expressing a query. Heuristics are very helpful when they are correct, but a PITA when they fail, so there always needs to be a way to override them. Especially in this case, specificity is a heuristic that fails so often that many authors have decided the benefit they get from selectors is not worth the specificity trouble and prefer to ditch selectors altogether and just use classes + JS for the querying logic!

Proposed solution

A new pseudo-class (name TBB, perhaps :filter()?) that works exactly like :matches() but with zero specificity. That way, authors have control over the specificity of their rules, and can choose what is best for their use case.

Or, even :matches() itself, since it has not yet been implemented, and changing its specificity would solve #1027 at once.

Edited on Sep 15 to add :filter() and some more thoughts

cc @gregwhitworth who is a long-proponent of a similar solution.

I was initially skeptical but then found some cases where this would be useful; all in all I would be in favor of such a change to :matches.

FWIW one such example is that sometime you need to apply some form of css reset for an element to work properly (because it comes from another framework and doesn't like the fact you override flex-direction to column by default for all elements) so you want to unset flex-direction again inside that element but doing so means that the reset will override any selector targeting the content of the element if its selector is less specific than the selector you use to target the reset root.

Or, even :matches() itself, since it has not yet been implemented

What's wrong with WebKit's implementation of :matches()?

I think about this nearly every single day. Agree this would be worth doing!

(For those wondering where my comment went, I integrated it into the first post and then deleted it)

I have a component with a lot of states, but I want to have a single class. I do this with data attributes now, but it increases specificity. Currently it's something like this (Suggest naming this :is)...

.button {
    ...styles 

    &:is([data-size=small]) {
        ...styles
    } 
    &:is(:focus) {
        ...styles
    }
    &:is([disabled]) {
        ...styles
    }
    &:is([data-selected]) {
        ...styles
    } 
}

I'm convinced by this reasoning; in particular, that "div, but minus these three specific ones" should be capable of being overridden reasonably, instead of blowing up to a 3-ID specificity.

Do we want to stick with this "something that makes its contents specificity-0", or try and generalize this to solve specificity hacks more generally? I'm not 100% sure how we'd do the latter in a future-friendly way (we've gone back and forth with precisely how many categories are in "specificity"), but I guess just sticking with the Big Three would be fine. (When we've tried to insert something else, it's for significant semantic differences, like scoped vs not, or inline vs not.)

Hmm. If we simplify and say that it has to be a compound selector only, then the grammar's pretty easy; if you want more complexity, you just nest a :matches() in. I think I'm in favor of the simple, short :is() naming, as this is more-or-less a no-op wrapper; every selector is an "is" filter already. Then you could control specificity like :is(.foo, 1 2 3) to give it the specificity of 1 ID, two attrs, and 3 tagnames. Leaving the specificity off defaults it to 0 0 0.

(I suppose we could allow a full complex selector, as commas don't interfere with that, and just require :matches() if you want a selector list. But maybe good to keep it simple - it's just a modifier to a single selector. We let you do a full compound selector, rather than limiting to a single simple, to avoid verbosity in a common case - .foo:is(.bar):is(.baz) is identical in meaning to .foo:is(.bar.baz), no reason to require more parens than necessary there.)

Do we want to stick with this "something that makes its contents specificity-0", or try and generalize this to solve specificity hacks more generally?

I'm in favor of a generalized approach.

What about something that just turns off specificity at the stylesheet level, and for those stylesheets everything is order based? This would allow authors to easily control when they wanted specificity to work as an override and when they wanted to ignored it and treat it purely as a query.

This would also help with resets and third-party stylesheets, and make it much easier for them to never clash with first-party styles.

Maybe something like:

<link nospecificity rel="stylesheet" hef="path/to/reset.css">

@tabatkins
Interesting idea, certainly more readable than current specificity hacks!
However, I wonder if it would be better to add single-argument :is() to level 4 and extend to allow for a second argument in Level 5? I'm a bit concerned that the extra functionality might slow down implementations, and since selectors don't fall back as gracefully as other unsupported CSS features, adoption will be slow anyway.

What about something that just turns off specificity at the stylesheet level, and for those stylesheets everything is order based? This would allow authors to easily control when they wanted specificity to work as an override and when they wanted to ignored it and treat it purely as a query.

While something like this could be useful in some cases (as you mention, resets are a prime candidate), I'm not sure it should be the only way to override the specificity heuristic. Specificity can be a useful concept, it's just that the inferred specificity is often wrong.

Also, you don't want any author rule to be able to override any rule in the third-party stylesheet. E.g. your library may have a .button component, you don't want their div or even * rule to override that, otherwise it becomes impossible to style anything.

Speaking about current specificity hacks, in CSS Selectors 4 there is already a way to build complex selectors with the specificity of a single class using nested :not() pseudo-classes (proposed by @kizu and proven to work in WebKit). Maybe it could be useful as a reference?

kizu commented

Having something like that :is() instead of the nested :not() hack would be so much better of course.

Though, I'm still thinking about (maybe alongside this :is()) having some way of creating your own cascade level, which you could then place above or below the default author one. This would allow either to import any external library on a level below, or write your styles on a level above, or even write code in multiple levels, like according to @csswizardry's ITCSS.

I understand that that goes beyond the scope of this exact issue, but in my opinion this would cover some of the cases much better and with much less code from the authors (and I think it should be also really easily implementable, the main problem would be in coming up with syntax and handling all the nuances). Below I'd briefly write what I managed to come up with, if that sounds good and there is interest for something like that or at least for discussion, I could create a new issue for it maybe (for [css-cascade] probably?).

  1. By default all the author CSS goes to the default โ€œNormal authorโ€ level (or โ€œoriginโ€, but I like the term โ€œlayerโ€ for this thing more).

  2. Now, it is possible to create a new โ€œlayerโ€. There are now two possibilities: either this layer would be nameless, or with a set name:

  • Nameless layers: @layer {โ€ฆ} โ€” by default everything that would go into those nameless layers would be put into one layer/origin that is above the one they were declared at. There should be also a way to put those not above, but below the current level, either with some keyword or stuff like @layer (position: below) {โ€ฆ}.
  • Named layers: @layer foo {โ€ฆ} โ€” whenever you declare a new layer this way, it would be placed above the previous declared one (or below if used with a keyword). Then, all the next @layers with the same name would be merged into this place, so the first occurrence matters.
  1. Layers can be nested one into each other, and there should be a way to handle things similar to how we can now handle stacking context & z-index (we should be able both to put the layer somewhere in the global context, or only manage it inside the current layer).

Basically, that's it. There are a lot of nuances and ways to implement some of this stuff, but: the main idea is to have a simple way of separating big chunks of code into independent layers similar to how the cascade of origins works now, basically allowing authors to create multiple author origins (or โ€” split the current author's origin into multiple layers, as all those styles should still be at its place in the cascade).

And, yes, the idea is still raw, and if there is interest we can discuss it in a new issue I guess? And, anyway, I think there regardless should be a way to handle the specificity of selectors like with is(), and I like the proposals for it above.

@kizu yeah, @fantasai had a similar idea, you should post about it and link to this issue as well!

kizu commented

Ok, I'll try to find time on this weekend to write up what I have in more details :) And I'm glad to hear someone already had similar ideas! If there are any links to something like that (maybe in csswg mailing lists or elsewhere?), I would be happy to read it.

As @FremyCompany mentioned, I've toyed with a few ideas in this space - primarily enforcing a specificity score at the stylesheet level. That said, there is the potential for more author confusion in this space as you're essentially introducing another layer of specificity (eg: on or off per origin/document/at-rule/stylesheet whatever is decided). The only reason I had opted for stylesheet level (I initially wanted to just opt for off/on for an entire document) is because with components you won't have the same control over whether the components you may be utilizing want/need to cascade and depend on specificity.

I would discourage this one selector being the only selector that nullifies the specificity because that is even more confusing to the additional layer IMO. I think if we do decide this is worth addressing then we should really consider all of the use cases and the way to make this as intuitive to authors as possible.

inoas commented
  • ๐Ÿ‘ for :is() as a pendent to :not() on the same specificity level - so the authors have the freedom to respect strict specificity
  • ๐Ÿ‘ for :filter() like :matches() without specificity - however maybe there can be a more general purpose way to disable/lower specificity of a selector/selector-part?

๐Ÿ‘ for :is() as a pendent to :not() on the same specificity level - so the authors have the freedom to respect strict specificity

But... isn't that exactly what :matches already does? I would rather have :is or :when be the name of the current :filter proposal. Maybe if you could clarify to me what the difference would be between :not(:not(x)) and :matches(x), then I would reconsider.

Actually, the more I think about it, the more button:when(:hover) really appeals to me. Just look at it: input:when([disabled]). Isn't that wonderful? ^_^

kizu commented

@FremyCompany The nested :not() with a single selector would be the same as :matches(), but with nested :not() its possible to hack things around for having a specificity of just one class (see http://kizu.ru/en/fun/controlling-the-specificity/#negation-of-negation).

Though, I agree that we can totally have :matches() to be just a shortcut that would keep the specificity, and then we could have the :when() (I like that name too) or something similar that would have no specificity added.

@kizu I see. That's a creative use of :not() ;-)

I would prefer something that states very clear what the purpose is. Something like div:nospecifity(:not(#foo):not(#bar):not(#baz)) or even :nospecifity(div:not(#foo):not(#bar):not(#baz)). It will follow the sequence only. Rethinking the latter I am not sure if it makes any sense because everything else has a specifity so it will be always overridden.

@dansajin I understand the need for explicitness but :nospecificity() is a pain to type and โ€” even worse โ€” a pain to read, especially when used multiple times in the selector.

@FremyCompany and I spoke about this at length, walked through a few different scenarios and the design of when() or is() is growing on me. With that said, the issue that @dansajin pointed out is a similar annoyance to me. One thing that I noted to @FremyCompany is that you may, say as an author want your entire stylesheet to have 0 specificity so you need to have this selector on every one. We realized that sass solves this problem but that's cumbersome, IMO.

I'm not saying I have the perfect solution here, but what about an at-rule that within any selector gets the same treatment as when() or is(). This allows for not repeating the function - as well as allowing for something like @no-specificity { } or similar to explain what is occurring since when() is essentially combining a filter and nullifying specificity. One downside from this approach (I'm sure people will find others) is that if you only want one selector such as the example above input:when([disabled]) you'd have an additional lines of code due to using an at-rule while when() would be concise.

I was actually going to suggest that an at-rule might be good here too, but didn't want to get ahead of myself. Pretty nice for custom elements with stuff that exists in the light DOM I think, I've been in a bunch of scenarios where I wanted my default styles to have very low specificity but require attributes or classes to differentiate

I think both are useful.
The problem is that nullifying specificity is rarely desirable.
Imagine that every universal selector or type selector from the library user will override anything from the library stylesheet.
The good thing with the pseudo-class is that we can see how authors use it and design the at-rule accordingly, since the at-rule is syntactic sugar for the pseudo-class.

Regarding the name, I like how :when() reads, but I also like the brevity of :is(). Iโ€™m fine with either.

A new pseudo-class (name TBB, perhaps :filter()?) that works exactly like :matches() but with zero specificity. That way, authors have control over the specificity of their rules, and can choose what is best for their use case.

This is a good proposition because it does what !important is sensibly used for, only in the opposite direction.

works exactly like :matches() but with zero specificity

This would be magically useful!

Suggest naming this :is

The terseness of :is() gets my vote.

Although, considering:

every selector is an "is" filter already

Presuming there are reasons why :() is not an option?

I guess it would be more difficult to talk about without an explicit nameโ€ฆ

It seems to me that some specificity within the function would be desirable. What if it was 1/1000 (or less) the strength of what is would be if it was outside the function?

So, for instance, .foo:matches(a) would have more specificity than .foo, but less than a.foo. And .foo:matches(a#bar) would have more specificity than .foo:matches(a), but still wouldnโ€™t beat .foo. Wouldnโ€™t that give us the best of all worlds?

It seems to me that some specificity within the function would be desirable. What if it was 1/1000 (or less) the strength of what is would be if it was outside the function?

Specificity is not a number. You just can't divide it by a number. Making this work would require transforming the specificity into a potentially-infinite integer list (because by recursivity a:matches(.foo:matches(#id)) should now beat a:matches(.foo) but not a:matches(a.foo) etc).

Sorry. I tend to think of ID selectors as 10x of class selectors, and class selectors as 10x of type selectors, etc. But that only works if the counts are less than 10 in each slot. The problem lessens if you use base 100 instead of base 10, I guess. But let me rephrase to be more like how the spec explains it:

If โ€œAโ€ is the count of id selectors, โ€œBโ€ is the count of class or attribute or pseudo class selectors, and โ€œCโ€ is the count of type or pseudo-element selectors, then instead of just looking at the counts in the order of โ€œa,b,cโ€, you would look at โ€œa,b,c,a1,b1,c1,a2,b2,c2โ€, etc., where the โ€œ1โ€ means one level of :matches(), โ€œ2โ€ means 2 levels of embedding :matches(something:matches(this-selector)), etc.

And if recursion is a problem, we can either limit the number of embedding to some smallish number, or just say that it is limited by memory constraints of implementation.

But the thing Iโ€™m getting at, is that you still have useful specificity within each level of the function embedding, which doesnโ€™t affect the specificity of the level above it, except for ties.

I don't understand why we're going down the heuristic lane again with things like "1/1000th of specificity" when the whole point of this feature is to cancel an unsuccessful heuristic. Typically when you do that, you want to be explicit, not give people another heuristic that could go wrong.
Tab did suggest a second optional parameter for adding specificity, if that is desired, and I agreed (just expressed concern that maybe it should be in the next level).
It seems to me that we are overcomplicating a rather simple feature in the last few comments.

Agreed. This should start by canceling specificity entirely, so you can add filters to a selector without hecking up your cascade, and possibly also have a specificity control on it. More heuristics and complications defeat the original point entirely.

Forget about โ€œ1/1000 of specificityโ€, and read my next post. Selectors inside a *:matches() function would always lose to those outside it, just as class selectors always lose to ID selectors. What could go wrong?

I just think that you can have your cake and eat it too, by doing it the way I described. The cascade would be internally very useful still, without hecking up anything outside of the function. We donโ€™t have to throw the baby out with the bath water.

@bradkemper Iโ€™m really not following what exactly is the problem youโ€™re seeing with nested :is(), nor what exactly youโ€™re proposing to fix it.

FWIW, I'm not supportive of this proposal either. I was just pointing out that its technically expensive to do and therefore unlikely to get any implementer traction.

Saying whether or not it has enough use cases is beyond my desire to debate this topic, so I just didn't comment on that (but I tend to agree I do not believe people want this behavior in the uses cases I've seen; in the cases where you want use this, you usually want to use source order and direct control).

EDIT: Just to clarify, these previous comments do not apply to Lea's original idea. That one is easy to implement and both greg and myself have seen clear user cases and demands for such a feature.

@LeaVerou,

The problem is not with nested :is(). It is that having zero specificity inside the function just seems too drastic to me. The problem you described is that it it increases the specificity of the whole complex selector to such a degree that it makes it harder to override, or that it itself overrides things you donโ€™t want it to. I think that problem can be overcome by just extending the existing specificity rules, so that the specificity inside the function doesnโ€™t significantly influence selecting, except to break ties in specificity outside the function (just as class selectors donโ€™t matter for specificity except to break ties in ID selectors).

So, the old specificity rules is (roughly) that when there is a tie in ID selectors, you look at class selectors. If that is a tie, you look at type selectors. I would add to that, so that if type selectors are tied, then look at ID selectors inside the :matches(). If that is still a tie, look at class selectors inside the :matches(). If those tie, then look at type selectors inside the :matches(). If those are tied, then look at ID selectors inside the embedded :matches(). And so on.

This allows you to write selectors that are as weak as you like compared to existing selectors, solving your originally stated problems. And inside the functions, you still get the great and important benefits of specificity-based cascading.

This would allow authors to write rules that donโ€™t override things they donโ€™t want to override, and would allow library authors to write rules that were easy for others to override, but without submitting to the tyranny of rule order.

And you could write many rules, with extremely low specificity, without worrying about something like * { max-height: 1000in) (a rule designed to prevent Android from randomly messing up font sizes) from accidentally overriding all the max-height values inside your :is()or matches() functions.

PS for my scheme to work, the :is()or :matches() pseudoclass would also not add its own pseudoclass specificity to the equation. Only the selectors inside it would work as Iโ€™ve described.

The problem you described is that it it increases the specificity of the whole complex selector to such a degree that it makes it harder to override

A lot of people just want to use specificity for the core of their matching, but source order for tiny variations on a selector, without having to refactor anything if they change some condition from "a class being present" to "a pair of attributes having certain values" as their apps evolve; your proposal would not help them achieve that.

From what I understand of the current state of css usage, with websites moving towards component-splitting of their files instead of type-splitting for their files, stylesheets files used in development have grown smaller and smaller, and targetted to specific portions of the application; using source order makes more sense than using the specificity cascade at that scale.

You still want specificity rules for more generic theming purposes, and to allow the style of one component to override its sub component' styles if needed, but "local state" of a component is something people don't want to have an impact on specificity, hence this proposal generating zero specificity.

It doesn't require major changes to how browsers do cascade unlike your proposal, and solves the currently most dire issue. I haven't heard anyone desiring your proposed behavior before. I don't want to say it doesn't have value, but it doesn't seem like an appropriate design to solve the most frequently-heard-about problem.

kizu commented

The second best thing about the zero-specificity matching (after its zero specificity itself) would be that it would work in the most straightforward and easily understandable (after you'll once get what it is doing) way. You won't need to do any calculations, as zero is the easiest stuff to operate. Having something inbetween would introduce an extra cognitive load: you'll suddenly need to look at the selectors in order to understand which exact specificity they have. And if selector would have multiple instances of this semi-specificity stuff?

I already can see how the zero-specificity stuff would be useful (and maybe when we'd have them we wouldn't even need that much the proposal that I described above?) for the stuff I do in CSS, and I need it yesterday. While just thinking about how to manage the sublevels of specificity makes me a bit dizzy.

Exactly what @kizu and @FremyCompany said. This kind of thing is needed yesterday, so complicating it further really doesn't help. If some specificity is desired, one can always make it so by using :is() for only a part of their selector (which I assume is how most people will use it, putting only the filters in :is()).

inoas commented

but without submitting to the tyranny of rule order.

I want to emphasis this note above^. I'd rather deal with specificity than file/rule loading order.

E.g.: :matches() should really NOT be changed but :filter() could be added to behave like matches but without adding any specificity. This gives authors freedom to respect to prefer the struggle with file load/rule order or specificity.

:matches() should also not be changed because it is out there in the wild already potentially breaking existing applications.


From what I understand of the current state of css usage, with websites moving towards component-splitting of their files instead of type-splitting for their files, stylesheets files used in development have grown smaller and smaller, and targetted to specific portions of the application; using source order makes more sense than using the specificity cascade at that scale.
You still want specificity rules for more generic theming purposes, and to allow the style of one component to override its sub component' styles if needed, but "local state" of a component is something people don't want to have an impact on specificity, hence this proposal generating zero specificity.

... and ...

While just thinking about how to manage the sublevels of specificity makes me a bit dizzy.

Again: Would declarative-shadow DOMs help because they could reset styles and work around specificity issues on a component based level?

kizu commented

Again: Would declarative-shadow DOMs help because they could reset styles and work around specificity issues on a component based level?

For my use cases โ€” no. I've already mentioned ITCSS โ€” I'm using something similar to this, and saw other people using something similar to this. For our cases, having a better control over specificity means:

  1. We would be able to create a better โ€œdefaultโ€ styles (example: normalize.css โ€” it has selectors like abbr[title], which are harder to override from your styles) easier and without a fear that adding new styles would mean we'd need to override stuff (we could have complicated rules for basic typography of elements like h1 + p, li > p:first-child etc. but with a specificity of one element, thus easily overridable).

  2. We could make it sure the modifiers (in BEM notation) for our elements would always override the default styles, even if we'd need to have those default styles complex enough (like having a .input class which has different styles for textarea.input & input.input, but in a way later introduced .input--bright would override both of those more complex selectors).

  3. With build tools like PostCSS or anything similar we could make it so that different levels of ITCSS wouldn't override each other (and those different levels can surely be used together on the same elements). Right now it is possible only by adding an excessive amount of extra classes/[class] to selectors, which is clearly a hack.

All of those cases (and there are more of them) don't have anything shadow DOM would help with.

inoas commented

As for default styles, having a way to disable or lower specificity would really be great ๐Ÿ‘ That covers your 1. and 2. IMHO (I am a user/contributor of Marx.css which is IMHO an opinionated normalize.css and having lower specificity will help doing what Marx/normalize do a lot easier).

However do you agree that :matches should not be overwritten to allow authors to work with specificity rather than having to depend on 3rd party tool-stacks (like PostCSS et al.)? Wouldn't a new :filter() fit your bill?

kizu commented

I'm more for :matches() for having its specificity in a place, and for :is() for having zero specificity. Having a zero-specificity complex selectors would surely make it so it would be possible to write complex stuff without relying on third-party tools, though they could still be helpful even in that case by making some things easier.

This is a good proposition because it does what !important is sensibly used for, only in the opposite direction.

@Stolzenhain , For the longest time, I've half-jokingly suggested to my coworkers that we need a complementary !unimportant keyword that we could apply to a selector. It's good to see that this basic concept is getting some traction.

Something like this would be nice:

@specificity lower {
    @specificity lower {
         ...
         @specificity none {
                 ...
          }
     }
}

The Working Group just discussed Functional pseudo-class like :matches() with 0 specificity, and agreed to the following resolutions:

  • RESOLVED: Add to selectors level 4 with a TBD name.
The full IRC log of that discussion <leaverou> topic: Functional pseudo-class like :matches() with 0 specificity
<eae> leaverou: As we all know specificity tries to infer importance from selectors. Resulting specificity might not always be logical.
<astearns> github: https://github.com//issues/1170
<Chris_> github, delete all comments
<eae> leaverou: My favorite example of specificity not being a good heuristic is using the not pseudo class.
<leaverou> div:not(#foo):not(#bar):not(#baz)
<eae> leaverou: ^^^
<eae> leaverou: In this example we want to target all dives except three, yet gets very high specificity.
<eae> leaverou: Especially for libraries, when trying to be specific, it is hard to override.
<eae> leaverou: uses something called BAM(?) encodes selector in class name and uses js to apply it.
<bradk_> BEM
<TabAtkins> s/BAM/BEM/
<Chris_> .how__many__people__have__hear__of__bem
<eae> leaverou: Willing to not use selectors at all, to bypass specificity.
<bradk_> http://getbem.com/introduction/
<eae> leaverou: One way to fix this would be to define selectors with a known specificity of one, would allow last selector win and make it easier to override.
<fantasai> q+
<eae> leaverou: I.e. put all nots in a single pseduo class. Easy solution vs other ones like per origin.
<eae> leaverou: Lets one be very specific with regardess to specificty, can be selected per selector and solves most of the known problems.
<eae> leaverou: Something that could be done as a pre-processor.
<eae> leaverou: Many names have been proposed, we can bikeshed that.
<eae> fantasai: Seems like a reasonable idea to me. The fact that authors can chose which parts of the selector applies to specificity sounds good to me.
<bkardell_> ?+
<eae> fantasai: Lower priority for an entire style sheet, library author might want to allow the entire stylesheet to be allowed to be overriden by author rules.
<Rossen> q?
<eae> leaverou: Example: in ?? there is a toolbar that has a class of mv-bar, also class of mv-ui that means applpy default style. Want author to be able to overrule using just mv-bar but I don't want their "div" rules to override.
<bradk_> q+
<astearns> s/??/mavo/
<Rossen> ack fantasai
<Rossen> ack bkardell_
<eae> bkardell_: I don't think they are mutually exclusive. May be that you can do an awful lot for a whole bunch of things and we know we can do that easily.
<eae> bkardell_: For a number of polyfills that I have worked on this would have been really useful.
<eae> bkardell_: There are things like headings that need to take aria roles into account that make them have very high specificity which makes it hard to override.
<TabAtkins> q+
<Rossen> ack bradk_
<eae> bradk_: Seems to me like we could solve this without taking specificity all the way down to zero.
<eae> bradk_: Specificty only matters when there is a tie.
<eae> bradk_: If there is a tie when it comes to ID or class, if the ID selector inside the funciton was more specific then outside the function that would solve the same problem while still allowoing specificity.
<Rossen> q?
<fantasai> Dael, here's the diagrams for Nat's presentation on line grids; please insert them in the correct section of the minutes. :) https://lists.w3.org/Archives/Public/www-archive/2017Nov/att-0008/CSSWG_2017.11.6_nmccully.pdf
<eae> leaverou: As dicussed in issue, if we have fractions of specificity that introduces new levels of specificity and no one is suggestion that the entire thing doesn't have specicifity. All the classes and IDs outside of it still applies. It allows the specificity to be controlled. To have it count as a class you would just add it to the end, a bit hacky.
<eae> bradk_: No use case for specifying it for the entire selector?
<eae> leaverou: Yes but usaully not. You would only want to [put some criteria in the pseduo class. Like all the not for example.
<eae> leaverou: Makes it less predictable. Now we know that we can count the number of IDs, number of classes, tags etc. If it is always zero it is very obiovus, if not it makes it much more complciated to compute it.
<Rossen> q?
<Rossen> ack TabAtkins
<eae> TabAtkins: I agree in general with what leaverou is saying. Authors can often do just fine when specificity is in order. Opting out or in-order seems ot match what users want.
<eae> TabAtkins: AS for chrome, we're happy with this, and would like to implement the stornger version of matches. This is easier, we might do this firts.
<eae> TabAtkins: We're supportive.
<Rossen> q?
<eae> florian: Let's put this in level 4 for now, we don't have a five.
<eae> fantasai:
<eae> Rossen: Let's add it to four.
<eae> fantasai: Very simple feature, as long as we're happy with the name.
<eae> ericwillgers: What about web platform tests?
<eae> fantasai: Not in CR yet, not needed.
<eae> <laughter>
<dbaron> q+
<eae> dbaron: One comment: I think it is worth nothing that it is not clear how easy it would be to implement matches. This has most of the same risk.
<Rossen> ack dbaron
<eae> dbaron: One of the things with selectors, they're heavily optimized. Implementing without optimizaions not very useful. With optimizations is quite a bit of work and not clear how quickly that can happen.
<eae> fantasai: Start with implemented subset.
<eae> TabAtkins: WebKit goes beyond spec, also has support for pseduo elements.
<eae> dbaron: Caution in that it's being tied to a feature which has an uncertain future.
<eae> fantasai: De-risk by having certain things in level 4 vs 5.
<eae> dbaron: Other alternatives that solves leaverou use cases.
<eae> leaverou: I don't want to reduce *all* of it to zero but only a part.
<bkardell_> ?+
<Chris_> q?
<eae> dbaron: I don't have a syntax proposal at this time but would avoid tie to branching combinators.
<eae> TabAtkins: Earliest version didn't support that, does not.
<eae> does now.
<bkardell_> ?-
<eae> fantasai: Making up a completely new unrelated syntax seems silly and doesn't make sense. Cut down on the syntax instead.
<Rossen> q?
<eae> dbaron: What doesn't make sense to me is spec moving so far ahead of what implementors are willing to do. Implementor by-in was not a factor.
<eae> fantasai: Disagree, you're arguing against it based on implementation priority.
<Chris_> s/by-in/buy-in
<eae> dbaron: you're acting like we can only do everything or nothing.
<fantasai> eae, that's not what I said
<eae> fantasai: Not what I said.
<fantasai> at all
<eae> dbaron: I'm fine with the proposal but I do not think it's the only one.
<eae> leaverou: If implementors aren't willing to do that at the moement shouldn't we discuss that?
<eae> dbaron: I think I bought this up when we went to CR
<eae> fantasai: Selectors are not in CR yet.
<eae> dbaron: But people are goimg ahead to implement it.
<leaverou> s/aren't willing to do that/aren't willing to implement a part of :matches()/
<eae> dbaron: This is the problem with sticking things in editors draft.
<fantasai> There shouldn't be anything in Selectors that didn't have a WG resolution to add.
<eae> Rossen: Would you prefer to see this go in in another way? If not can we try to settle on a resoluiton and go on.
<fantasai> If there is, the editors made a mistake.
<fantasai> If there was a resolution and you didn't like it you should have objected.
<eae> dbaron: Fine with matches without combinators under a different name.
<fantasai> Being angry about it now is neither helpful nor fair.
<bkardell_> q+
<eae> leaverou: I'm fine with that (adding combinators later)
<eae> TabAtkins: The no combinators version is the one that desugars effecitvely. Start with simple version.
<eae> leaverou: Still supports commas, right?
<Rossen> q?
<eae> TabAtkins: Yes
<eae> bkardell_: Is there a suggestion to take combinators out of matches level 4 as well?
<eae> TabAtkins: Yes
<eae> Rossen: Are you OK with that?
<eae> leaverou: Yes, can we have a resolution?
<dbaron> fwiw, we did discuss moving selectors4 to cr at least in https://lists.w3.org/Archives/Public/www-style/2015Jul/0349.html
<eae> Proposed resolution: Add to selectors level 4 with a TBD name
<eae> RESOLVED: Add to selectors level 4 with a TBD name.
<eae> fantasai: Do we have a list of candidate names?
<eae> leaverou: is, when, and filter
<eae> Rossen: Any particular favorite we can resolve on right now?
<eae> ericwilingers: I like filter
<eae> Rossen: filter has the most plusses on github?
<eae> leaverou: No, I think it was either is or when.
<dbaron> filter is also the name of a property
<eae> Rossen: You all work it out.
<eae> Rossen: let's move on.

For what it's worth (responding to my own comments in the minutes above), I might be wrong about which aspects of :matches() are hard -- maybe the branching doesn't add that much complexity -- and difficulty with specificity wouldn't be present here, although there may still be issues with implementing the various class/tag/id and bloom filter optimizations to make :matches() equivalent in performance to the old way of saying the same thing. It does appear I had the opposite opinion before (about how bad the branching of combinators resulting from allowing combinators inside :matches() was). But I think it's still a relatively complex feature, and that tying the ability to drop specificity to :matches() does hurt the chances of getting the ability to drop specificity sooner.

o-t-w commented

:is is the perfect name. Keep it simple and implement as soon as possible ๐ŸŽ‰

The issue raised at the end of the IRC discussion is important. Having a property and a selector named the same thing isn't ideal so I think filter would be a bad choice.

I filed #2143 for further discussion on the name, as we haven't decided on it.

I also marked this as an open issue in the draft and named the pseudo-class :something() for now so that it's really obvious that it needs a name.