将选择样式应用于开槽元素?

Applying selection style to slotted elements?

我正在尝试将 ::selection 样式应用于 Web 组件中的开槽元素。

这里有一段小代码来说明这个问题:

window.customElements.define('x-widget', class extends HTMLElement {
    constructor() {
        super();

        this.attachShadow({mode: 'open'});

        const template = document.createElement('template');
        template.innerHTML = `
            <div>TEMPLATE</div>
            <div><slot></slot></div>
        `;

        const style = document.createElement('style');
        style.textContent = `
            :host {
                display: content;
                contain: content;
                color: red;
            }
    
            :host::selection, ::selection {
                background: red;
                color: white;
            }
    
            ::slotted(::selection) {
                background: red;
                color: white;
            }
        `;

        this.shadowRoot.appendChild(style);
        this.shadowRoot.appendChild(template.content.cloneNode(true));
    }
});
<x-widget>CONTENT1</x-widget>
<x-widget><div>CONTENT2</div></x-widget>

这是一个演示:https://jsfiddle.net/ov4xmqsr/

选择样式应用于除 <div>CONTENT2</div> 之外的所有文本。有没有办法在组件中使用伪元素选择器?

你不能,因为 slotted 内容没有移动到 shadowDOM,它仍然在 ligthDOM.

您在 ligthDOM 中设置了开槽内容的样式(在本例中是主要 DOM)

有关非常详细的答案,请参阅:

我添加了额外的 CSS 以显示:

  • 使用变量(穿透阴影DOM)声明颜色

  • 使用 #selectable DIV 包装器选择两个自定义元素
    亲自看看 x-widget ::selection 选择器 会做什么

Select all text:
<div id=selectable>
  <x-widget>CONTENT1</x-widget>
  <x-widget><div>CONTENT2</div></x-widget>
</div>
<style>
  body {
    --selectionBackground: green; --selectionColor: white;
    font-size: 2em;
  }
  #selectable ::selection {
    background: var(--selectionBackground); color: var(--selectionColor);
    font-weight: bold;
  }
</style>
<script>
  window.customElements.define('x-widget', class extends HTMLElement {
    constructor() {
      const template = document.createElement('template');
      template.innerHTML = `<div>TEMPLATE</div><div><slot></slot></div>`;
      const style = document.createElement('style');
      style.textContent = `
            ::selection { /* colors only template text, not slot content */
                background: var(--selectionBackground);
                color: var(--selectionColor);
            }
            ::slotted(*) {  /* selectors select HTMLElements! */
                color: red; /* CONTENT1 is TEXT, NOT an HTMLElement! */
            }`;
      super().attachShadow({mode: 'open'})
             .append(style, template.content.cloneNode(true));
    }});
</script>