Lwc: [css] add support for `::slotted` selectors

Created on 4 Feb 2018  路  11Comments  路  Source: salesforce/lwc

There are few issues with ::slotted that we should take into consideration, more details here: https://github.com/w3c/webcomponents/issues/728

standards-gap

Most helpful comment

No, I don't recall having this conversation.

@Templarian If we are able to implement the ::slotted selector properly I don't see any blocker handling complex compound selectors. I don't see any issue make those selector work once we agree on how the trees should be flattened.

All 11 comments

We need a volunteer to work on this. My mental model is easy, we can have a custom attribute for when the slot is supposed to display slotted content, and in that case, we do:

::slotted(input){
  color: red;
}

compiled into:

::slotted(input),
[c-foo_foo]>input {
  color: red;
}

That seems good enough, and should work fine in both cases, synthetic and native. @pmdartus what do you think?

I think the hardest part here is the replicate the fact that the ::slotted() pseudo-element should be applied after the flattening.

Here is a complex example: https://jsfiddle.net/wLmbq354/1/

<x-parent>
    #shadow
    |   <style> ::slotted(div) { color: red; } </style>
    |   <x-child>
    |       #shadow
    |       |   <style> ::slotted(*) { color: blue; } </style>  
    |       |   <slot name="slot3">
    |       <slot name="slot2" slot="slot3">
    |           <slot name="slot1">
    <div slot="slot1">
    <span slot="slot1">

As far as I understand the specification, the pseudo-selector should be applied to the elements that are returned by slot.assignedElements({ flatten: true }). So if you invoke it on slot2 and slot3 it should return the div and the span.

Before discussing how this will be implemented in LWC, I just want to make sure we got this right. It appears that Webkit is the only engine implementing the spec properly:

  • Webkit: div is red and span is blue
  • Blink and Gecko: div is red and span is black (the tree is not properly flattened)

@caridy Can you confirm we have the same understanding of the spec here so I can open bugs on respective engines?

That being said, I don't think the [c-foo_foo] > input will make the cut if we want to support flattening properly. I think we will need to add another attribute for slotted content, but I think it will be tricky to get that right.

I don't fully understand the issue, let's chat about it.

@pmdartus Looked around to see if Chrome had any open bugs and I don't see anything resembling this in the tracker. I think I understand the bug.

@caridy Not sure how far this conversation went, but assuming no complex nesting would it be possible to implement a restricted ::slotted support.

::slotted(div) { }
::slotted(div:hover) { }
::slotted(div:hover)::before { }

Seeing as it translates to specific styles for legacy the performance issue seems minimal.

I don't remember the offline conversation about this... maybe @pmdartus remembers it. we can always chat again :)

No, I don't recall having this conversation.

@Templarian If we are able to implement the ::slotted selector properly I don't see any blocker handling complex compound selectors. I don't see any issue make those selector work once we agree on how the trees should be flattened.

@pmdartus any update on the interop issue that caused the blocking of implementing this as I just discussed utilization of this psuedo and wasn't aware that we didn't allow it. Do you have a repro testcase to test the interop and if it does exist we can get this fixed in engines that are blocking our implementation.

The repro can be found in the original post. The issue is still reproducible today.

@gregwhitworth Before opening a bug against a specific engine, I would like to understand which engine is wrong. TBH, this issue is reaching the limits of my understanding of the CSS spec. Do you know someone that might help?

This actually doesn't have to do with CSS itself, but the implementation or interpretation of this specific aspect of the HTML specification. Specifically stating:

The ::slotted() pseudo-element represents the elements assigned, after flattening, to a slot.

So basically, when you follow the algo (which honestly there's so much indirection) is if the above is true. Given the rest of the implementation and that the content appears in the slots (I updated the fiddle to add slot eventing to ensure that Safari/FF/Chromium behave the same and they do).

So effectively it comes down to the above definition of the elements, once flattened. Upon my naiive reading of the algo I think Safari does the correct thing here. And then when you consider that there is a test within WPT specifically testing nested slots that technically passes but does not actually pass in Chromium/FF but does in Safari here I think I'm correct that Safari has the correct behavior. I'll file a bug on Chromium.

This issue was discussed in the CSSWG and the interop difference found here is due to a bug in Safari and in all other areas they are interoperable with other vendors. Since default content can be styled using normal styling it was resolved to clarify the spec using examples (since people on the call that implemented it were confusing what HTML flattening would do to slots) and change the spec to read as the current interop behavior.

Discussion is here: https://github.com/w3c/csswg-drafts/issues/5482

So this issue should be unblocked for support.

Was this page helpful?
0 / 5 - 0 ratings