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>
Mendy
  • 7,612
  • 5
  • 28
  • 42
  • https://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." – disinfor Jun 28 '21 at 17:29
  • @disinfor None of the examples in my question are text nodes, they're all actual elements – Mendy Jun 28 '21 at 17:53
  • For instance, `first-letter` is not an element - it's a pseudo reference to text. – disinfor Jun 28 '21 at 18:02
  • @disinfor 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 `

    `), 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`.

    – Mendy Jun 28 '21 at 18:26
  • 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. – disinfor Jun 28 '21 at 18:55

1 Answers1

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));
}
Danny '365CSI' Engelman
  • 16,526
  • 2
  • 32
  • 49
  • 1
    I'm somewhat curious now... do you have an aversion to the properly-capitalized name of "Firefox"? :-) – TylerH Jun 28 '21 at 18:03
  • 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 spaces – Mendy Jun 28 '21 at 18:20
  • @Mendy Perhaps you understand them as "basic" selectors (see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors), rather than "simple". Formally, simple selectors are defined here: https://www.w3.org/TR/2018/CR-selectors-3-20180130/#simple-selectors – TylerH Jun 28 '21 at 18:21
  • 1
    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: https://github.com/WICG/webcomponents/issues – Danny '365CSI' Engelman Jun 28 '21 at 18:32