Skip to content

Complex selectors in ::slotted() and :host()? #5

Open
@Westbrook

Description

@Westbrook

Now that all browsers support complex CSS selectors inside of :not(), what prevents the same within ::slotted() or :host()?

Browser announcements for reference:

Naively, this seems like the same internals would go into both resolutions, so much so that the idea of not just getting deep children, but resolving cascades up to next shadow root seem like they should just come for free now.

Example:

<parent-element>
    #shadow-root
        <div class="wrapper">
            <child-element>
                #shadow-root
                    <style>
                        ::host(.wrapper *) {
                            color: blue;
                        }
                        ::slotted(.wrapper *) {
                            color: red;
                        }
                        ::slotted(p a) {
                            color: green;
                        }
                    </style>
                    <p>This should be blue.</p>
                    <slot></slot>
                <p>This should be red...</p>
            </child-element>
            <child-element>
                #shadow-root
                    <style>
                        ::host(.wrapper *) {
                            color: blue;
                        }
                        ::slotted(.wrapper *) {
                            color: red;
                        }
                        ::slotted(p a) {
                            color: green;
                        }
                    </style>
                    <p>This should be blue.</p>
                    <slot></slot>
                <p>This should be red...</p>
            </child-element>
        </div>
        <child-element>
            #shadow-root
                <style>
                    ::host(.wrapper *) {
                        color: blue;
                    }
                    ::slotted(.wrapper *) {
                        color: red;
                    }
                    ::slotted(p a) {
                        color: green;
                    }
                </style>
                <p>This should NOT be blue.</p>
                <slot></slot>
            <p>This should NOT be red... but, <a href="#">This should be green</a></p>
        </child-element>
</parent-element>

Use cases:
The ability to use :host(.wrapper *) aligns with the use of complex selectors on top of the idea of self references like :host([open]) etc. while allowing for the capabilities of :host-context() that never found footing outside of Blink, without the need for a completely new selector. This sort of functionality gives a component author the ability to outline specific realities about the delivery of their component is specific context. This is similar to how the details > summary:first-of-type element gets upgraded to have toggle UI: https://codepen.io/Westbrook/pen/QWGLdxP

This sort of .parent * resolving selector is interesting, and would seem like you'd want to apply it to content in a ::slotted() selector for all the same reasons, thought I do see how having the extended capabilities in the :host() selector outlined above would allow you to make this same ::slotted(.wrapper *) selection with :host(.wrapper *), in the case that we can't have it all. Certainly the more important addition of complex selecting in ::slotted() has to do with the ability to target styles on non-direct children.

A great power feature of an element with shadow DOM is its ability to encapsulate a world of both functionality and styles. Slotted content puts a really cool inside/out, outside/in twist on that. The ability to progressively enhance content with a custom element, turning vanilla content into vibrant content currently falls a little short when the encapsulated space can't really bring descendent content into the family without addressing it with styles from JS. While the content being slotted means we do have the means to style it from the outside, the benefit of slotting it into an element with shadow DOM should be that we're not required to. Imaging the child-element in the above example is an article or aside or callout that should take on a new background color when upgraded, without the ability to control the color of the anchor tag grandchild element it's possible that the content can become unaccessible without requiring advance knowledge of custom element usage (if a custom element and the :not(:defined) selector is even available) for a consuming developer to ensure that their content will be delivered appropriately.


It's possible that this issue belongs in https://github.com/WICG/webcomponents/issues, and I'm happy to move it if so. However, I wanted to start by asking this as an opportunity to learn about the possible reasoning behind the currently available APIs and gather community interest in the capabilities it unlocks before attempting to more formally position it as a proposal for standardization.

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