Combining ::slotted with pseudo-elements
Asked Answered
G

1

6

I'm trying to figure out what's the deal with combining pseudo-elements with the ::slotted selector, looks like it works with some but not with others and I can't find any documentation listing the selectors it works with

Here is a demonstration of the problem, notice how some pseudo-selectors take effect while others don't

class TestElement extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({mode: 'open'});
        let template = document.querySelector("template");
        this.shadowRoot.append(template.content.cloneNode(true));
    }
}

customElements.define("test-element", TestElement);
<template>
    <style>
        
        ::slotted(*)::first-line { /* doesn't works */
            color: red;
        }
        ::slotted(*):first-letter { /* doesn't works */
            color: red;
        }
        ::slotted(*) {
            max-height: 3em;
            overflow: auto;
        }
        ::slotted(*)::-webkit-scrollbar { /* doesn't works */
            width: 3px;
        }
        ::slotted(*)::-webkit-scrollbar-track { /* doesn't works */
            background-color: red;
        }
        ::slotted(*)::selection { /* doesn't works */
            color: red;
        }
        ::slotted(*)::placeholder { /* works */
            color: red;
        }
        ::slotted(*)::marker { /* works */
            color: red;
        }
    </style>
    <slot></slot>
</template>

<test-element>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente
    doloribus ullam fugit ipsum laborum velit architecto, provident dolore
    at, aperiam quaerat officiis aliquid magni sed expedita totam dolor
    doloremque odit.
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente
    doloribus ullam fugit ipsum laborum velit architecto, provident dolore
    at, aperiam quaerat officiis aliquid magni sed expedita totam dolor
    doloremque odit.
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente
    doloribus ullam fugit ipsum laborum velit architecto, provident dolore
    at, aperiam quaerat officiis aliquid magni sed expedita totam dolor
    doloremque odit.</p>
</test-element>

<test-element>
    <input placeholder="Placeholder">
</test-element>

<test-element>
    <li>Li</li>
</test-element>
Glosseme answered 28/6, 2021 at 16:33 Comment(5)
developer.mozilla.org/en-US/docs/Web/CSS/::slotted "Note also that this selector won't select a text node placed into a slot; it only targets actual elements."Allopathy
@Allopathy None of the examples in my question are text nodes, they're all actual elementsGlosseme
For instance, first-letter is not an element - it's a pseudo reference to text.Allopathy
@Allopathy hmm.., I don't think this is what they mean by "text node", I think they're just saying that there has to be and element there (e.g. the <p>), not that the selector can't select text within the element, but I might be wrong. But regardless, even if you're right, it would only explain first-letter and first-line not the others like selection and webkit-scrollbar.Glosseme
agreed. This is an interesting question! For ::selection and webkit-scrollbar I wonder if it's because they aren't necessarily part of the actual shadow dom - and ::selection still refers to the actual text and not a basic/simple selector.Allopathy
S
0

Good find on ::placeholder and ::marker

But ::marker does not work in Mozilla's browser (haven't tested safari)

In general ::slotted() only takes a simple selector;
see: ::slotted CSS selector for nested children in shadowDOM slot

Side note: your constructor can be written as:

constructor() {
  let template = document.querySelector("template"); // valid code *before* super()
  super() // sets and returns this scope
    .attachShadow({mode: 'open'}) // sets and returns this.shadowRoot
    .append(template.content.cloneNode(true));
}
Signore answered 28/6, 2021 at 17:52 Comment(4)
I'm somewhat curious now... do you have an aversion to the properly-capitalized name of "Firefox"? :-)Commensurate
What constitutes a simple selector? I can't find anything in the answer you link to, that would explain why ::placeholder is more simple than ::selection. Looks like what they call a simple selector is a direct selector as opposed to a selector of a parent to a child i.e. a selector without spacesGlosseme
@Glosseme Perhaps you understand them as "basic" selectors (see developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors), rather than "simple". Formally, simple selectors are defined here: w3.org/TR/2018/CR-selectors-3-20180130/#simple-selectorsCommensurate
Dunno, would have expected no pseudo selector to work. Maybe ::placeholder is somewhat different than the others because it operates on a Form element. Ask the engineers: github.com/WICG/webcomponents/issuesIllinium

© 2022 - 2024 — McMap. All rights reserved.