-
Notifications
You must be signed in to change notification settings - Fork 668
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[selectors] Pseudo-class to indicate when a slot has content #6867
Comments
I have also needed this on several occasions. At the moment, you need to (at the minimum) inspect A typical use case for me is to hide ( So being able to target a slot with assigned content is the most pressing use-case. Though I think it's also worth considering whether there should be separate pseudo-class for each of these states:
|
I'd like to point out that a
I'm quite keen myself to set a |
Perhaps inline with
A good partner to this spec would be #6620 |
This seems like a related request in the WICG space: WICG/webcomponents#936 |
The CSS Working Group just discussed
The full IRC log of that discussion<emeyer> fantasai: I wanted to know if this is something we want to pursue. plinss was asked whether or not we can check to see if something has slotted content. Is this something we want to do?<emeyer> TabAtkins: The use case makes sense and the argument is reasonable. The fact you can’t tell if text content has been slotted in leaves a whole. I say was call it ‘:slottted’ <fantasai> s/slottted/has-slotted/ <emeyer> PaulG: Is the example intended to be a slot name? <emeyer> TabAtkins: ‘::slotted’ will select anything slotted into that slot. <emeyer> fantasai: Tab and I should draft a proposal. <emeyer> Rossen: Would this be level 4? <emeyer> fantasai: No, 5 <fantasai> ACTION: Tab + fantasai to draft into Selectors 5 <emeyer> RESOLVED: Take this up for Selectors 5, fantasai and tabatkins will come back with proposed text |
in the example the |
Can you elaborate on what you're thinking of? The As I said in the minutes above, I think |
@tabatkins where are you seeing the Would be we able to do something here along the lines of Is there any benefit in being forward looking to the discussion in #7922 and make it a combinator? Maybe that doesn't make sense in this case... |
An interesting edge case to consider will be slots with default content as well. Does default content count as
|
I'd say no, because that But perhaps there may be more use cases. |
Great nuance in:
That I'm not quite sure how you could combine |
Now that I think of it, it's not just slot:not(:has(*)):not(:has-slotted(*)) {
display: none;
} ( <slot name="title">${this.cardTitle}</slot> I wasn't aware that default slot content is returned by |
It's on the
I'd say no. It's not slotted content, and in particular, it's not useful to detect slotted content in this case if this is true. That is, if |
We have a number of SSR users who really need this selector. There a few reasons this is critical in some SSR implementations:
It seems like the idea of a new selector is fairly well received... can this idea be added to an upcoming csswg meeting? |
In the case of Shoelace, we're using imperative DOM code to do slot detection which, as @justinfagnani mentioned, doesn't work on the server. We can probably work around some of these checks by changing structure/display so empty slots collapse, but this is very uncomfortable and won't solve all of our use cases. As it stands, without such a selector, we can't get SSR fully functional. This has, unfortunately, been a pretty big hurdle for adopters who want to use our custom elements with metaframeworks + SSR. |
I'm using the same imperative code mechanism as Shoelace above to detect slots having content. A css selector would be amazing. |
It isn't though. @LeaVerou's point here is very important:
|
Non-functional @claviska also reminded me of a potential footgun here: does a single whitespace text node match |
How many of these were for named slots? You can only slot elements into named slots, so
I think you have to reproduce this behavior. An important aspect to consistency is fallback content. A whitespace text node will prevent fallback content from showing. I don't think we want |
Apologies I misread. In that case both make sense to have, but again (hubris incoming) I think they can both be specified and implemented reasonably straightfowardly in unison, it's certainly how I'd prefer to tackle it.
I'd prefer to see |
Agree that this is a nasty foot gun that needs to be addressed. It's not exclusively a CSS issue since it prevents fallback content from displaying. Ideally we'd solve the core issue and not just add a CSS bandaid, but I propose the following in the interests of making concrete progress:
If we don't get this right, the following would show a red box and that seems, to me, a bit absurd. <x-foo>
<template shadowrootmode="open">
<style>
slot:has-slotted {
display: block;
height: 20px;
background: red;
}
</style>
<slot></slot>
</template>
</x-foo> |
Unfortunate as it may be, I am tending to agree that consistency is more important, and we need to reproduce the JS behavior, while providing some kind of mechanism to at least make these cases detectable. 😢 What that mechanism would be needs more design discussion @keithamus looking at the PR, it seems there are many more design decisions to be made with the functional version, which would make the non-functional version at least easier to specify, if not also easier to implement. That doesn't mean we won't work on the functional version — if anything getting the non-functional version in ASAP paves the way for working on the functional version, it doesn’t compete against it. |
Could you provide an example of that? I didn't think about the distinction, so I'm not sure.
Agree, tho I agree with Lea that it sucks. But yeah, I believe the major use-case of In the absence of that, I think @sorvell's idea of re: functional form, agreed with Lea. The resolution was for the non-functional form. We can pursue the functional form as well, but it can be done separately; CSS is fine with handling a pseudo with both forms. |
Yeah, in the ideal case I completely agree, but I worry that the fact that the behavior spans CSS and JS makes our typically glacial pace more cosmological here. It also seems like we're down the path of inconsistency already with |
That's not at all inconsistent. You can't do |
@sorvell That is not an inconsistency, I doubt |
Yup, my mistake. It is indeed getting hard to parse these functions =) |
Talking to @emilio yesterday, he confirmed my suspicion that |
The CSS Working Group just discussed The full IRC log of that discussion<lea> q+<khush> keithamus: has slotted is a pseudo class. it is the opposite of definition of default slotted <khush> has slotted means that it has been slotted <astearns> ack astearns <khush> we resolved on the issue to just have the ... pseudo-class <lea> s/... pseudo-/:has-slotted pseudo-/ <khush> a bare pseudo class. not functional one <khush> i want a functional one which takes a compound selector <khush> lea has raised a PR of non-functional pseudo-class <khush> could we resolve on both <khush> lea: there are distinct use-cases for both <khush> the non-functional version is not an alias for :has with * <khush> have chatted with implementors, bare version is easier <khush> i want it to move fwd <khush> there is confusion with has(slotted) <dbaron> s/with */with *, because the non-functional version also matches text nodes/ <khush> we don't have slotted pseudo-class, only pseudo element <khush> there is potential confusion in terms of authors not understanding <khush> but functionality is clear <khush> i'm not sure if i would be in favour of fallback based naming <khush> since we want it for other use-cases <emilio> q+ <khush> but just mentionning <astearns> ack lea <khush> emilio: the bare version is very straightforward <dbaron> s/i'm not sure if/we could name it something related to fallback, but I'm not sure if/ <astearns> ack emilio <khush> the functional version feels hard to implement. naming suggests we're looking at descendants. what's supported would be confusing <lea> q+ to also mention :has-slotted variant that excludes whitespace-only slotted nodes <TabAtkins> I don't think it would be that confusing. It would be interpreted basically identically to ::slotted() <khush> keithamus: there is confusion around what combinators would do <dbaron> s/for other use-cases/even if there's no fallback content/ <khush> should only match the slotted element <TabAtkins> If ::slotted(.foo) would match an element, :has-slotted(.foo) will match <fserb> q+ <khush> emilio: it might be worth naming it after nth-child perhaps <khush> has it been considered? <astearns> zakim, close queue <Zakim> ok, astearns, the speaker queue is closed <khush> the naming is off and confusing, otherwise it's fine <khush> the bare version is extremely simple to implement <khush> emilio: you mentioned you wanted it to also match fallback content. <khush> lea: if we wanna change the naming to not confuse with has, it could be fallback-show <khush> the matching would be the same logic <khush> q? <astearns> ack lea <Zakim> lea, you wanted to also mention :has-slotted variant that excludes whitespace-only slotted nodes <khush> lea: since this has to reflect the behaviour of existing js api <khush> even if only slotted is blank white space node it still has to match <khush> we want a bare slotted version which includes just whitespace <khush> is that easy to implement> <khush> ? <astearns> ack fserb <khush> fserb: maybe the name would be better as revered <khush> has-fallback-content for example <lea> :fallback-shown is also nicely analogous to :placeholder-shown. What happens with that pseudo-class if there is no placeholder on the input? <khush> keithamus: i like the symmetry between the 2. renaming would make them asymetrical and cause confusion |
Update: I submitted PR #10959 yesterday, @tabatkins reviewed it today, and I’ve also had chats with @emilio and @rniwa about implementation difficulty and they both said it’s trivial to do. Not sure who the Blink implementor is (@chrishtr @mfreed7 do you know?), but I imagine the answer would be similar. So, fingers crossed this could ship in browsers relatively soon, as it’s a nice quick win 🤞🏼 |
My team could take a look - sounds rather straightforward to implement. A few questions/requests:
|
@mfreed7 happy to implement in Chrome. We have some WPTs, I'll file a bug. |
Thank you @mfreed7!
Yes, though many are mixed with
Ideally the functional syntax should be separated into separate tests even if we resolve to add it. They are separate features and need to be tested separately.
Looks like someone beat me to it 15 hours ago! https://issues.chromium.org/issues/369883705 |
Thank you both! Looks like there's a lot of enthusiasm for the new pseudo class. Sounds like we're off and running.
In particular, thanks for this one! I can provide reviews, if needed. |
The CSS Working Group just discussed
The full IRC log of that discussion<emilio> Rossen9: who's best to summarize this one?<emilio> dbaron: was discussed yesterday according to github-bot <dbaron> https://github.com//issues/6867#issuecomment-2378207271 <emilio> keithamus: didn't resolve because I had a question about the functional pseudo-class <emilio> ... to do the same things I was talking about <emilio> ... wrt /slotted/ <emilio> ... I think we need to pick a direction, either we look into the slotted combinator or we look into :has-slotted() <emilio> q+ <dandclark> emilio: Did we resolve on the nonfunctional version? <emilio> keithamus: we resolved to that prior <emilio> ... but test were written for the functional pseudo-class <Rossen9> ack emilio <emilio> ... it seems the functional pseudo is more interesting to the WC community <emilio> ... but happy to investigate the combinator <emilio> emilio: Given :has-slotted() is dependent on whether we do the combinator, and the combinator kinda depends on what we do about the cascade order, I'd prefer to discuss the cascade order at least first, when TabAtkins is around ideally <dandclark> emilio: We can keep the tests as tentative or I can split it <dandclark> emilio: I think we need an issue about the cascade issue <dandclark> ...wasn't clear that was the main complaint about the slotted selector <emilio> ACTION: keithamus to open issue about ::slotted() cascade order |
I think #6466 is the related issue - it talks of specificity but it looks representative of the cascade order issue. |
Tested The behavior is good for simple cases but not useful for nested composition. Perhaps this can be solved via #10771.
|
I'm going to
Agenda+
as I'd like to capture a resolution that the current behaviour of not matching the flat tree is okay, and perhaps to resolve to investigating a way to match the flat tree (though perhaps this is If web developers could please provide signal that the current behaviour as prototyped in Firefox and Chrome (that |
I really like having anything available in this area (is there any way that I can further explain the high level of important the web component developing community places on this API?). I am super excited about the implementation currently available in Chrome/Firefox (so many things we could never do have already been opened up to us with this API). However, not being able to select against the flattened tree will be a hard blocker on this API; maybe not today, maybe not tomorrow, but it will come up (much like questions around white space being "slotted") that would be better to be answered today, if only directionally. Personally, I can certainly be appeased with the selector matching <div><template shadowrootmode="open">
<div>
<template shadowrootmode="open">
<style>
::slotted(input) {
color: red;
}
</style>
<slot></slot>
</template>
<slot><input value="not styled" /></slot>
</div>
</template></div> Practically, we do need to support the spread. Questions:Does that mean multiple selectors? Does Functionally, will component authors be doomed/required to "know" the slotted content depth? <div>
<template shadowrootmode="open">
<div>
<template shadowrootmode="open">
<div>
<template shadowrootmode="open">
<style>
p {
color: red;
}
slot:has-slotted(slot:has-slotted(slot:has-slotted(p))) + p {
color: green;
}
</style>
<slot></slot>
<p>Styled content</p>
</template>
<slot></slot>
</div>
</template>
</div>
</template>
<p>Slotted content.</p>
</div> Does a combinator approach mean that Could any of these practically address selecting when content is delivered via the hole in Many thanks to all who are investing time into making this a high-quality and powerful additions to the web platform! 🙇🏼♂️ |
Based on the 3rd row of the table here, it's my opinion that: The bare form of Note, it's slightly confusing to call this the flattened tree because The basic use case for this:
There are 2 separate issues which I think should be considered orthogonal to
|
I'm developing several web components and I'm finding a need to tell when a slot has content or not. (e.g. to apply margins or not so empty slots don't impact layout, but layout well when they do, etc.)
The :empty pseudo-class applies when the slot doesn't have direct content, even when it has slotted content, so doesn't work. Using slot:has(::slotted(*)) wouldn't detect text-only content.
Once possibility would be to redefine :empty to detect slotted content, but it may be useful to keep the current behavior to differentiate empty slots from slots with default content (and the change may break exiting content). So a new pseudo-class that only detects slotted content may be useful.
The text was updated successfully, but these errors were encountered: