- 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