Skip to content

[selectors4] Name the “functional pseudo-class like :matches() with 0 specificity” #2143

Closed

Description

@fantasai

In Issue #1170 we decided to add a functional pseudo-class that is exactly like :matches() but has zero specificity. However, we didn't decide on a name.

Suggestions in that thread included :is(), :when(), :filter(), and :nospecificity(). It was noted that having :filter() as a selector and filter s a property might be confusing, and that :nospecificity() is a pain to type. Additional suggestions, comments, and clarifications welcome.

Activity

  1. LeaVerou commented on Dec 28, 2017

    @LeaVerou
    Member

    I would vote for :is(). It's short, and it explains what it does. IIRC most people were in favor of :is() both in the thread and at the F2F. If you want an explicit resolution, we could add it to the agenda.

    This is the twitter thread where I asked authors for ideas: https://twitter.com/LeaVerou/status/928426600558862337
    As you will see, the results are not very useful.

    Regarding the other names:

    • :when sounds time-related
    • :nospecificity is ridiculously long and prevents any possibility of expansion in the future to allow setting specificity, as @tabatkins suggested.
    • :filter is confusing because it sounds related to the filter property and the filter() function.
  2. SebastianZ commented on Dec 29, 2017

    @SebastianZ
    Contributor

    :nospecificity is ridiculously long and prevents any possibility of expansion in the future to allow setting specificity, as @tabatkins suggested.

    At least the latter point could be avoided, of course, by using :specificity() instead. Nonetheless it's still very long and hard to write.

    So, I also vote for :is(), even when it rather indicates a check and not something to set the specificity.

    Sebastian

  3. SelenIT commented on Dec 29, 2017

    @SelenIT
    Collaborator

    I'm for :is(), as it :is() easy to memorize as kind of acronym for "Ignore Specificity" :)

  4. Loirooriol commented on Dec 29, 2017

    @Loirooriol
    Contributor

    Since #1170 was already resolved it may be too late for this, but shouldn't #1027 be resolved before adding a new functional pseudo-class?

    It seems probable to me that the specificity of :matches needs to be fixed to avoid performance problems in some cases, and then :is could become redundant.

  5. SelenIT commented on Dec 30, 2017

    @SelenIT
    Collaborator

    I’m not sure that :matches() can, and needs to, be “fixed”. For me, the summary of #1027 is that :matches() doesn’t have any special performance problems per se (except it allows to write seemingly short selectors equivalent to terribly long selector lists, but this problem is not new, it often occurs with CSS preprocessors as well). Also, :matches() has been supported in Safari since 2015, and there is intent to implement it in Chrome, so changing it can break the interoperability. And, AFAIK, it wasn’t meant to affect specificity in any way, it’s sole purpose was to be syntactic sugar for shortening the lists of selectors with common parts for readability and reducing style bloating. The :is() selector, on the other hand, was introduced specifically to explicitly control the specificity, so I doubt that it could become redundant.

  6. Loirooriol commented on Dec 30, 2017

    @Loirooriol
    Contributor

    Yes, just syntax sugar, but the problem is that if you just desugar it naively then you get an exponentially-long selector. Preprocessors don't matter, what matters is the CSS they produce, and it's acceptable for a CSS engine to take more time if the CSS is absurdly huge. But if the CSS is not huge, then it should be fast (e.g. that's why :has is not allowed in the dynamic profile).

    If Safari implemented :matches, maybe there is some efficient algorithm. But I suspect they might not be calculating the specificity of :matches on the element that ensures a maximum specificity, which probably is what the spec should properly define. Sadly I have no Mac to test.

  7. fantasai commented on Jan 1, 2018

    @fantasai
    CollaboratorAuthor

    My concern with :is() is that it will be logically seen as the inverse of :not(), even though the inverse of :not() is :matches(): the specificity behavior of :not() and :matches() are matched, and :not(:not(selector)) behaves as :matches(selector), not as :is(selector). But linguistically “is” and “not” seem to form a pair.

  8. Loirooriol commented on Jan 1, 2018

    @Loirooriol
    Contributor

    What about swapping :is and :matches, then? So :is would be analogous to :not and :matches would have 0 specificity.

  9. SelenIT commented on Jan 2, 2018

    @SelenIT
    Collaborator

    Well, maybe then we can avoid the confusion if we could use the pattern proposed in #1170 by @tabatkins and add an extra optional argument to the existing :matches() instead of duplicating its functionality in a new pseudo-class at all?

    So while :matches(...) would behave as it currently does, for example, :matches(... as 0,0,0) would have the behavior of the proposed :is() (zero-specificity matching), and :matches(... as 0,1,0) would match any of its arguments with the specificity of the single class. It would be backwards compatible with the existing :matches() implementations and wouldn't introduce any ambiguity in what is the inverse of :not(). Moreover, the similar extra argument could be added to :not() as well, making the behavior of :not() and :matches() symmetric.

    Or is it too late to make such changes in Level 4?

  10. LeaVerou commented on Jan 2, 2018

    @LeaVerou
    Member

    Yup, we could rename :matches() to :is() and introduce an extra argument, which could only be 0 at first, and later expand to the full specificity triplet.
    I.e. div:is(#foo, as 0).

  11. SelenIT commented on Jan 2, 2018

    @SelenIT
    Collaborator

    Wouldn’t renaming :matches() require making it an alias for :is()? Or will it make the existing WebKit’s shipped implementation (and probably the Blink’s implementation being currently developed) non-conforming?

  12. tabatkins commented on Jan 2, 2018

    @tabatkins
    Member

    We're not renaming :matches(); it's already shipped in Safari and I think Firefox and Chrome are soon to ship?

    I'm still okay with just adding the functionality to :matches(), with the default being the current "specificity of the most specific branch that matched". If we do make a separate function, I'm still happy with :is(); the possibility for confusion is there, but oh well.

  13. inoas commented on Jan 3, 2018

    @inoas

    So since when has short-lived vendor implementation ruled what happens to a standard?

    I don't get it what's wrong, this is not yet another piece of software that you (or someone else at big-vendor-x) can throw away in some years and replace it with something else entirely and somehow I got the feeling that that's the recent predominant mind set. /rant :-(

    Without much details to rephrase what @fantasai says:

    • If :not() and :matches() are the inverse of each other they should have inversed names for easy understanding and usage.
    • If :is() and :not() have inversed semantic meaning, they should behave like that and not unexpectedly do something else.

    Logical options that make sure developers in future are not the hell confused about it (and TWBS-div-soup-hell shows most, are):

    • A) Rename matches() to is() - use matches() for the new 0-specificity feature discussed here.
    • B) Alias is() and matches() and find a new name for the feature proposed here instead of matches().

    So why don't we collect alternate names for the current matches()-proposal and if we can find something really reasonable we can alias is() and matches() and deprecate matches()? What's so wrong about that?

  14. inoas commented on Jan 3, 2018

    @inoas

    If my last comment is true, that would leave us with:

    • :nospecificity() - Agreed that it is hard to type, long, wants me to write :no-specificity() instead, wants me to add typos to "specifity" by accident and leaves no option to add specificity features later on. Pretty much worse than :is(), IMHO.
    • :filter() - I rather much would have the same word in different contexts doing different things (as expected), than logical pairs of words doing something else (:is() vs :not()).
    • :when() - I don't think the interpretation as only "time" related is a problem @LeaVerou? LESS, Elixir and PostgreSQL use it for logical conditions just fine, so why is ":when sounds time-related" a problem?

    So these are all sane options without creating unexpected developer pain:

    1. Use matches() for the new implementation and rename current matches() implementation in the wild to is() - Issue: Vendor Safari has to adapt.
    2. Use when() for the new implementation and alias current matches() to is() and deprecate matches() - Issue: None?
    3. Use filter() for the new implementation and alias current matches() to is() and deprecate matches() - Small Issue: re-use of the same word in different context means it does different things.

    Edit, here are some more from @LeaVerou's Twitter post.

    • :extend()
    • :decorate()
    • :augment()
    • :if()
    • :catch(), and I'd like to add:
    • :apply()
    • :case()
  15. 90 remaining items

  16. jonathantneal commented on Jul 26, 2018

    @jonathantneal
    Contributor

    I’m legitimately (and not sarcastically) sorry to you if my critique was not profound enough, but please do re-read my post, looking specifically for :if().

    All of that aside, if you wish to continue bikeshedding how we ought to bikeshed, I would kindly ask that we move that discussion to Twitter, where civilized discourse may abound. 😄

  17. bkardell commented on Jul 26, 2018

    @bkardell
    Contributor

    :nil() and :zero() seems to be the only ones where it will be clear "why we used this pseudo-selector". So they've got my vote.

    @tzi - and :nospecificity

    @Tyler-H FWIW, while I definitely share the sentiment that perpetual bikeshed isn't a good thing, it seems to me that part of why the WG has made no real decision is that none of the options seemed particularly great (at least this has been my feeling - kind of noncommittal/least worst). Since then, I feel like some options that seem at least as good have been added. From other conversations I am led to think that perhaps some other WG members feel this. I think that updating the table and asking whether it is more valuable for the pseudo to be clear or extendable to including a numeric specificity seems valid and potentially helpful. Perhaps the WG can resolve one way or another on that much at least and we can eliminate several items?

  18. sarimarton commented on Aug 1, 2018

    @sarimarton

    I've read the whole thread, and I'm aware of that now it's supposedly only an :if vs. :when question. But I'd like to get back a little bit (if only to show why :if and :when are mistaken tracks).

    It's notable how far we've got from :is. :is is by far the most intuitive choice, everybody gets that in their mind in the first (or second) place, and there's a reason for that (no, not the funny acronym, which in my view has zero relevance). A selector, by nature, is a predicate, which says something about the matching element. Linguistically, nouns, adjectives and verbs and negation play well as predicates. Not surprisingly, if we look around among the current pseudo-classes, we find exactly these word classes. Any other word class, which the alternatives belong to, including :if, :when, :nospecificity, :zero etc., essentially breaks this logic and so hits a little bit in the gut. Obviously they can been read as parts of a sentence, but the reading logic is custom in that case. :if is not really a first-order predicate in itself.

    Now came the problem with the imperfect contrast with :not. I'm not sure how this can be more important, than the above. :is is an exception in the system which has no specificity calculation, and having the most generic name plays well with this fact. Technically this imperfect contrast is not a problem at all. It's actually beneficial, because it makes :is(:not( meaningful, and it reads well.

    On the other hand, in the future, other strategies might appear for specificity management. To me, for example, using the zero-specificity selector (whatever name it has, and however short it is) extensively, particularly with wrapping the whole selector to keep it on zero, is not a good long-term solution. It's just code repetition. We might have a higher order scope for specificity, maybe something like this:

    <link rel="stylesheet" type="text/css" href="framework.css" specificity=1>
    <link rel="stylesheet" type="text/css" href="mycustom.css" specificity=x>

    which might act as the highest order in the calculation placeholders: x,0,0,0. I know it's out of scope (and maybe it is proposed already?), but my point is that specificity strategies can easily evolve above the selector level, so we shouldn't get lost in the supposed significance of the :is vs. :not question. IMO, :is would nicely fill a gap in the API (linguistically) and the zero-specificity function is just a good motive to get it not just as an alias (to :matches). Imperfect contrast with :not is not a problem at all. And we can leave :matches as it is now.

    Sorry for being too long.

  19. fantasai commented on Oct 23, 2018

    @fantasai
    CollaboratorAuthor

    I mentioned this during the meeting and I'll repeat, I think it's important for this selector to be short and also for it to be clear about how it's different from :matches()/:not(). Subtly different names that imply subtly different behavior without actually implying the difference through their names are very confusing.

    I'm rather less concerned about extending to an arbitrary specificity level, it's reasonably likely that we never do that. Numbers for ordering are not the best, see e.g. BASIC and its goto statements, or tabindex if you want a more recent example. Ideally any solutions to specificity wrangling would incorporate some concept of higher level structures rather than numbers on the number line.

    :zero() and :nil() aren't great in many ways, but at least they fulfill the two criteria I mentioned: they're short, and they imply something about what makes them different from :matches()/:not(). Or :is()/:not() if we lived in an ideal world and could rename :matches(). :)

  20. css-meeting-bot commented on Oct 23, 2018

    @css-meeting-bot
    Member

    The CSS Working Group just discussed [selectors4] Name the “functional pseudo-class like :matches() with 0 specificity”.

    • RESOLVED: Name the selector :where
    The full IRC log of that discussion <mstange> Topic: [selectors4] Name the “functional pseudo-class like :matches() with 0 specificity”
    <mstange> fantasai: Lea is not here, do we want to talk about it?
    <mstange> fantasai: Anybody have anything to add to this discussion? There's no clear "this is definitely what we should do" resolution.
    <TabAtkins> New suggestion: smoosh()
    <Rossen> github: https://github.com//issues/2143
    <fantasai> https://github.com//issues/2143#issuecomment-408128027
    <TabAtkins> Sorry, :smoosh()
    <zcorpan> -webkit-appearance: smoosh
    <mstange> fantasai: This takes a list of selectors of which any can match. Unlike the :matches selector it basically zeroes out the specificity: anything you put inside has a specificity of zero.
    <mstange> fantasai: This gives you more control about which parts of the selector affect the specificity and which down.
    <mstange> fantasai: The only question is what to name it.
    <mstange> fantasai: Some of the suggestions didn't get any traction.
    <mstange> fantasai: We don't have any suggestion that is clearly better than the other ones.
    <mstange> fantasai: My concern with a lot of these is that it is not very clear for :if or :where why this is different from :matches.
    <mstange> ... It's different because of the zero specificity, so the name should have something to do with that.
    <mstange> franremy: Last time we had narrowed it down to three.
    <mstange> fantasai: New ones were added after last time.
    <mstange> franremy: We almost agreed on one of them last time, don't remember which one.
    <mstange> franremy: Would prefer to not expand the length of the list of candidates.
    <mstange> dbaron: To make progress, we need to say "Nobody leaves the room until we decide."
    <ericwilligers> Last time: if vs where
    <fantasai> https://lists.w3.org/Archives/Public/www-style/2018Jul/0027.html
    <mstange> fantasai: Our resolution last time was to narrow the short list to :if and :where, and we added :nil and :zero.
    <mstange> ... So we could choose between those.
    <mstange> Rossen: if, where, nil, zero, quash
    <mstange> Rossen: In that order, with if being 1 and quash being 5, go ahead and put in your preferred 3.
    <mstange> ... In the order of preference
    <fantasai> 1 = if, 2 = where, 3 = nil, 4 = zero, 5 = quash
    <franremy> 1 2 ... 4 3 5
    <iank_> 2, 5, 3
    <fantasai> 5, 3, 4, 1, 2
    <cbiesinger> 2, 1
    <florian> 1, 2
    <TabAtkins> 3, 2, 1
    <heycam> 2, 1
    <futhark> 2 3 5
    <dbaron> 4 3 2 5 1
    <fantasai> https://github.com//issues/1170
    <ericwilligers> 2, 1, 4
    <Rossen> 2, 1
    <eae> 3 2 1
    <melanierichards> 2
    <AmeliaBR> 2 4
    <tantek> 4 3 5 :ns (no specificity)
    <rachelandrew> 2, 1 , 3
    <emilio> 3, 1
    <Oriol> 1, 2, 4, but I would prefer any
    <emilio> fantasai: lol
    <bz> nsISelector
    <bz> That's NS
    <mstange> Rossen: A lot of votes for number 2 as the first choice
    <AmeliaBR> Why was `:is` dropped from the options?
    <mstange> ... Resolve on :where?
    <mstange> ... If anyone has a strong reason to change this, speak up now.
    <mstange> Resolved: Name the selector :where
  21. gibson042 commented on Oct 27, 2018

    @gibson042

    :zero() and :nil() aren't great in many ways, but at least they fulfill the two criteria I mentioned: they're short, and they imply something about what makes them different from :matches()/:not(). Or :is()/:not() if we lived in an ideal world and could rename :matches(). :)

    @fantasai We may not live in an ideal world, but I think we do live in one that's close enough to introduce :is() and redefine :matches() as a deprecated alias of it. What do you think?

  22. fantasai commented on Oct 27, 2018

    @fantasai
    CollaboratorAuthor

    @gibson042 Filed #3258 on renaming :matches() to :is(). If anyone has an opinion on it, please comment there.

  23. inoas commented on Oct 28, 2018

    @inoas

    TLDR: Thank you so much

    I predict :where() will lead to a new enlighten age of reset/base, classless, css libraries like https://github.com/mblode/marx and similar. In conjunction with the data attribute and other attribute selectors there will be a trove of options now to reset stuff without doing ANY harm.

    I love that the WG got through with it eventually and even picked a declarative/functional/semantic name (where over nil). There will be new reset stylesheets that won't interfere with any specificy issues and we will finally have a nice base to cover all different browsers and OS platforms. Obviously properties that affect form widgets (like appearance), outlines, highlights, scrollbars, overscrolling/touch etc. are now things that need to be resolved as quickly as possible so that it becomes easy to reset everything, or - everything but form controls, scrollbars, overscrolling etc.

    Thank you so much (:is() will follow as an alias of :matches() and sanity returns)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions