- From: Dael Jackson <daelcss@gmail.com>
- Date: Wed, 1 Jun 2022 20:23:41 -0400
- To: www-style@w3.org
========================================= These are the official CSSWG minutes. Unless you're correcting the minutes, Please respond by starting a new thread with an appropriate subject line. ========================================= Selectors --------- - RESOLVED: Remove special handling of :scope in :has() (Issue #6399: Remove the :scope dependency from the relative selectors definition) - RESOLVED: Remove special handling of :scope in relative selectors generally (Issue #6399) - RESOLVED: Disallow nesting :has() inside :has() (Issue #6952: Consider disallowing logical combination pseudo-classes inside :has()) - RESOLVED: No change; :host etc. continues to be allowed inside :has() (Issue #7212: Consider disallowing :host, :host(), :host-context() inside :has()) - RESOLVED: @supports uses non-forgiving parsing for all selectors (Issue #7280: Detecting :has() restrictions) - RESOLVED: Close no change (Issue #6845: Consider disallowing :has() outside the rightmost compound) - RESOLVED: Revert the resolution from #3760, removing the "no complex selectors" restriction from :nth-child() (Issue #3760: Defer complex selectors inside :nth-child() etc. to L5) ===== FULL MEETING MINUTES ====== +++ Selectors/:has() focused extra meeting +++ Agenda: https://lists.w3.org/Archives/Public/www-style/2022Jun/0001.html Present: Adam Argyle Rossen Atanassov Tab Atkins Bittner David Baron Oriol Brufau Tantek Çelik Emilio Cobos Álvarez Elika Etemad Chris Harrelson Brian Kardell Brad Kemper Rune Lillesveen Jen Simmons Alan Stearns Miriam Suzanne Scribe: fantasai Selectors ========= Remove the :scope dependency from the relative selectors definition ------------------------------------------------------------------- github: https://github.com/w3c/csswg-drafts/issues/6399 futhark: :scope was specced to have a special meaning inside :has, that it matches the selector matched by :has() itself futhark: It would be much simpler it kept the same meaning as it has outside of :has() TabAtkins: Making :has() give a special meaning to :scope wasn't a definitive choice, it just fell out of the definitions we had TabAtkins: I'm comfortable with removing this TabAtkins: Just need to do some edits to definitions futhark: There are complexities when it complexities for allowing :scope inside :has() futhark: It'll be easier to handle cases wrt shadow hosts if we make this change <TabAtkins> Yeah, :scope was invented for querySelector anyway, I'm comfortable boxing it off for just that purpose. fantasai: I think to the extent we might need such a functionality, we can choose a different syntax for it <emilio> +1 RESOLVED: Remove special handling of :scope in :has() TabAtkins: I would prefer to remove it for relative selectors in general, and redefine :scope to just be for .querySelector TabAtkins: I think we'll run into these problems in the future otherwise RESOLVED: Remove special handling of :scope in relative selectors generally futhark: Issue 7211 looks related astearns: Let's skip, I'll add a comment pointing to this resolution Consider disallowing logical combination pseudo-classes inside :has() --------------------------------------------------------------------- github: https://github.com/w3c/csswg-drafts/issues/6952 futhark: I think there is agreement to allow combinations like :is() and :where() futhark: But implementors want to disallow :has() inside :has() bkardell: I think that's my impression as well. I think Safari implements this way as well futhark: Implement in chrome and safari, but buggy futhark: Don't think need to change the spec at this point futhark: or to add any limitations, other than :has() TabAtkins: I support this <jensimmons> I've already found a useful usecase for figure:not(:has(:not(img))) { ... } fantasai: Proposed then that :has() cannot be nested inside :has() oriol: I think other combinations seem useful, but :has() inside :has() doesn't seem that useful bkardell: Originally wanted to disallow all of them, but based on feedback went back and made them work bkardell: said some perf implications, but seem livable-with bkardell: so let's just prohibit :has() inside :has() astearns: Other opinions? RESOLVED: Disallow nesting :has() inside :has() <TabAtkins> I mean, I'm sure there are use-cases for nested :has(), but they're not as obvious and clearly worth the complexity cost, so I'm happy with this. Consider disallowing :host, :host(), :host-context() inside :has() ------------------------------------------------------------------ github: https://github.com/w3c/csswg-drafts/issues/7212 futhark: Given resolution wrt :scope, at least from Chrome side, we agree that :host-context will never match inside :has() because it needs to have sibling/parent ... shadow tree futhark: not a perf problem, but it will never match futhark: Proposed resolution from our side is no change TabAtkins: :host will never match as final selector, but the example here ... <TabAtkins> .b:has(:host .a .c) TabAtkins: slightly simplified version of a selector in the issue TabAtkins: this would still match TabAtkins: However it's exactly equivalent to just moving the :host outside TabAtkins: If we were to ban it, wouldn't hurt anything, but is matchable in this instance bkardell: Because doesn't begin with a relative combinator TabAtkins: So evaluates globally against the context bkardell: This is where the whole weird context comes from bkardell: I think a lot of ppl would not expect that to match futhark: From impl side of things, it's not an important issue futhark: Removing special meaning of :scope means it's not a perf issue bkardell: So you would ... walk all the way up the tree? bkardell: Seems weird to me that this should match bkardell: Basically nobody would expect it TabAtkins: It's the same as putting :root in there TabAtkins: Why expect not to match? bkardell: Even in jquery etc., :has() you start matching at the boundary, you don't walk all the way up the tree TabAtkins: Am I misremembering this? <fantasai> :has(:is(:host .a)) <fantasai> maybe you mean something like that? fantasai: The host element doesn't necessarily have to be inside... fantasai: The host doesn't have to be in the :has() fantasai: When you have :is() tho, that doesn't necessarily get scoped. fantasai: So if you nest it like this, this could match. <fantasai> :has(:is(:root .a)) would match, for example TabAtkins: That's right, would do it fantasai: My inclination is to make this invalid, would be easier for everyone to understand and get it right astearns: You would get the same effect by moving :host outside of :has() TabAtkins: Yes <TabAtkins> A:has(:is(:host B)) rewrites to :is(:host A, A:host):has(B) bkardell: Previous example was one that Oriol pointed out. Did we agree to the opposite, that you can't use :is()? or did I misunderstand? TabAtkins: All other relational selectors are fine bkardell: What was proposal? TabAtkins: Make :host illegal inside of :has() context emilio: If no reason to disallow performance-wise, probably more work to disallow. But don't mind either way futhark: I don't have strong feelings either way astearns: Given confusion we just put ourselves through, I have a slight preference for disallowing astearns: because it's an unreadable way of expressing this bkardell: I agree TabAtkins: :host does have theoretical use in here, because if you want to select a top-level element in your shadow tree need to use ':host > element' TabAtkins: it's no more confusing than :root in this context TabAtkins: so that part doesn't bother me emilio: Why would you want to use direct child combinator? You can't have anything that's direct child of host in here bkardell: ... emilio: so :host :has(stuff) emilio: You would need to be :host(:has()) <TabAtkins> .foo:has(:is(:host > .top-level .bar)) TabAtkins: This is a meaningful selector TabAtkins: it's a .foo that has a non-top-level-.bar inside it emilio: Yeah, ok, fine emilio: Assuming there's no reason to ban it perf-wise, then seems fine to keep it astearns: I'm hearing a lot of "eh" TabAtkins: I suggest we leave as-is, unless on further investigation it has a perf implication <emilio> +1 futhark: I agree RESOLVED: No change; :host etc. continues to be allowed inside :has() Detecting :has() restrictions ----------------------------- github: https://github.com/w3c/csswg-drafts/issues/7280 emilio: It seems this is not going to have so many restrictions, so maybe not a big deal emilio: In case we wanted to restrict stuff like :host emilio: and then eventually potentially ... emilio: Not easy to detect which UAs would support it vs not emilio: since :has() uses forgiving parsing, anything you throw at it is valid emilio: It seems we're only going to restrict :has() inside :has() emilio: doesn't seem useful but complex, but may still matter... emilio: My point is that if we have any hope for unrestricting, it may be useful to be able to detect it when we do <jensimmons> +1000 emilio: If you put @supports :has(:has()) ... emilio: makes it a problem if you want to do something in the future emilio: you can always test the thing inside TabAtkins: Not true TabAtkins: :is()-disallowed pseudo-elements, for example TabAtkins: This sounds reasonable to me TabAtkins: Unsure about forgiving vs unforgiving jensimmons: I think it's a really good idea jensimmons: Having @supports parse as valid a thing that the browser doesn't support jensimmons: for the future, we need @supports to be accurate and true emilio: For FF it's easy, just passing down a flag oriol: I wonder if rather than adding hack in supports we could say that if you have either :has() or whatever that has this forgiving syntax, and all of the selectors inside it are invalid, then it would also be invalid oriol: It would be something like, if you have some invalid and some valid treat whole as valid oriol: So if you only have invalid ones, it would be invalid. If you have a mix, it would be valid oriol: So if using :has(invalid) then is invalid, and detect that without having to make supports change the syntax <emilio> oriol is saying that `:has(:random)` would be valid, but `:has(something, :random)` would be valid fantasai: OK, so I'm with jensimmons here. If the selector contains anything invalid, then it should return as invalid even if the invalidity is caught at a lower level emilio: Some precedent here wrt -webkit- stuff jensimmons: If this occurred to me as a developer, I wouldn't look it up. I would use @supports to detect support, e.g with color:red emilio: Especially if CSS author, unlikely to jump to using JS to check astearns: So proposed resolution is for @supports to use non-forgiving parsing for all selectors TabAtkins: yes <fantasai> strong +1 RESOLVED: @supports uses non-forgiving parsing for all selectors Consider disallowing :has() outside the rightmost compound ---------------------------------------------------------- github: https://github.com/w3c/csswg-drafts/issues/6845 futhark: raised by anttijk to [missed] futhark: Proposal is no change futhark: Safari doesn't have this restriction, and there are ways to optimize <fantasai> https://github.com/w3c/csswg-drafts/issues/6845#issuecomment-998484450 astearns: Proposed resolution is no change RESOLVED: Close no change Defer complex selectors inside :nth-child() etc. to L5 ------------------------------------------------------ github: https://github.com/w3c/csswg-drafts/issues/3760#issuecomment-1119234126 scribe: TabAtkins fantasai: We had agreed to defer complex selectors inside :nth-child() until level 5 fantasai: and :is() and :where(), etc fantasai: It seems like it's been implemented in :is()/:where()/:not() though fantasai: So I committed the edits to restrict it for :nth-child()/etc, but not for the others that have already implemented it. fantasai: So I want to know if we really do want this restriction for :nth-child(), or if impls are okay with just allowing complex selectors. fantasai: Oriol had a question about nesting :nth-child(... of :is()), the restriction would be recursive. astearns: So both those examples would be invalid? fantasai: Yes. fantasai: Or both valid, depending. fantasai: So question is, what do impls want to do? emilio: Since Blink and Gecko don't yet implement the "of <selector>" at all yet, I'd be okay with moving it to level 5. But we should implement it. fantasai: Note that this just about complex selectors in "of <selector>" fantasai: Not the general feature fantasai: so :nth-child(1 of .foo) would be valid in level 4, but :nth-child(1 of .foo .bar) would be invalid emilio: Don't think it matters much either way. When we get to implement it we'll probably do the complex selector form. emilio: Guess it matters how much it matters for Selectors 4 to have multiple interoperable impls, but we don't implement the simple selector syntax either in Gecko. <bkardell> +1 to move it to level 5 fantasai: Opinions from the Safari team? jensimmons: I think we've already implemented it TabAtkins: I know Safari has done at least simple selectors, dunno about complex <fantasai> https://www.software.hixie.ch/utilities/js/live-dom-viewer/?%3C!DOCTYPE%20html%3E%0A%3Cstyle%3Ep%3Anth-child(1%20of%20body%20%3E%20p)%20%7B%20background%3A%20yellow%3B%20%7D%3C%2Fstyle%3E%0A%0A%3Cp%3Estylethis astearns: In terms of spec advancement, punting complex selectors means we could promote level 4 as soon as simple selectors are done by multiple impls. But it's not clear to me if that's actually going to happen before complex is also supported. fantasai: It seems like webkit supports complex selectors in :nth-child() fantasai: So question is just to other impls - do you want to tackle complex selectors when you do the feature at all? Or do it stepwise? futhark: Don't have thoughts about it right now. emilio: Same emilio: I don't see anything terrible complicated about supporting complex selectors. emilio: Might make the invalidation a little trickier, but probably not by much. fantasai: Okay so if we don't know, and Safari has already done it, I suggest we remove the restriction. <bkardell> ok fantasai: If we need to add the restriction later we can do that. emilio: Sounds good. astearns: so proposed resolution is to undo the previous resolution and put complex selectors back into :nth-child(), until we see that this is a blocker for level 4 advancement astearns: Objections to reversing the previous resolution? (in issue 3760) chrishtr: Rune can you confirm if this is implemented this way in Chrome at the moment? futhark: We don't implement the "of <selector>" at all in Chrome yet TabAtkins: Right now everyone supports :th-child(), only safari supports :nth-child-(.. of selector) TabAtkins: We have a resolution on the books to restrict that selector to compound selectors TabAtkins: We're reversing that resolution chrishtr: So that won't have any effect on chromium and gecko shipping :has(), and forward compatible with us shipping the upgraded :nth-child() in the future TabAtkins: yeah chrishtr: So this is kinda just a technicality? astearns: Yeah just level wrangling astearns: Either we get a second impl of this in :nth-child(), or we get really close with everything else in level 4 and we defer *all* of the :nth-child() enhancements to advance the spec emilio: Or we get a second impl but that only did simple selectors, we could punt the complex selectors again. But doesn't matter much for impls right now. chrishtr: Sounds fine, doesn't affect our current impl plans. astearns: So, any objections? RESOLVED: Revert the resolution from #3760, removing the "no complex selectors" restriction from :nth-child() Issue look-through and next steps --------------------------------- chrishtr: Checking - we resolved all the items in this list? astearns: Yeah. (Some discussion about 3 and 1 being identical.) chrishtr: So all the issues blocking Chromium shipping have been resolved, this is amazing. chrishtr: Does anyone disagree? Any other issues outside this list? astearns: Separate issue if we want an official CSSWG resolution if it's okay to ship :has() even though the spec isn't advanced enough. chrishtr: Yeah just wondering about further technical issues that need discussing. astearns: You had the list of four, I found all the other :has()-related ones. All of them afaik emilio: Impl wise, there's only a matter of fixing support. emilio: Seems like this is tested and impls are interoperable, then it's useful emilio: I'm not sure if this should be in the spec, but given that perf of :has() is kinda a blocker in general... emilio: Like it needs to be interoperable to be useful. emilio: I'm aware of engines doing various optimizations, wondering if spec should say something about the complexity of matching :has() emilio: Even though the various impl optimizations are impl details, wondering if the spec should mention something about that. astearns: Also wondering if there should be tests for particularly tricky perf situations. astearns: Don't think WPT has a way of testing CSS perf. bkardell: They can time out and get flaky, at least. <TabAtkins> You can explicitly do timing, if you want. Just gotta write it explicitly. emilio: I think we have test like that for CSS var() expansion limit. bkardell: Unsure we can agree what's a "complex case" tho. emilio: :has() is quadratic or exponential by definition, basically. Everything we don't optimize is going to be worst-case complexity. [missed from emilio due to dog] astearns: If there are particular perf issues you're worried about, good to raise issues on the spec about if we need to handle certain edge cases. astearns: Can decide if this is an impl-specific thing, or if we do need it in the spec. astearns: If there are gotcha that every impl should handle, that should be in the spec. emilio: For some kind of UAs, it may not be a big deal, only for live UAs. bkardell: Yeah like Prince probably doesn't care nearly as much. TabAtkins: If you have particular concerns of things to point out, we're happy to put notes for implementers in the spec emilio: Sounds good, mostly just an idle thought. astearns: Any other :has() discussion?
Received on Thursday, 2 June 2022 00:24:22 UTC