【问题标题】:Combinators for multiple ::slotted elements多个 ::slotted 元素的组合器
【发布时间】:2020-09-05 11:26:23
【问题描述】:

如果有办法实现以下目标,我很感兴趣:

::slotted(input[type="checkbox"]:disabled) ~ ::slotted(label) {
  cursor: not-allowed;
}

通过在某些示例上对其进行测试,它不起作用。
Specification 没有说明这是否应该可行。 MDN 也没有涵盖这种情况。

我不想在shadow-dom 中包含inputlabel,因为我不想处理和/或复制这些元素的本机行为。

附:我知道我可以使用 javascript 来做到这一点(例如,通过将类添加到开槽 label),但我正在寻找一个简单的 css 解决方案。

完整示例:

<script>
  customElements.define('my-element', class extends HTMLElement {
    constructor() {
      super();
      const shadowRoot = this.attachShadow({mode: 'open'});
        shadowRoot.innerHTML = `
            <style>
              ::slotted(input:disabled) ~ ::slotted(label) {
                color: red;
              }
              ::slotted(input:disabled) + ::slotted(label) {
                color: red;
              }
            </style>
            <slot name="inputel"></slot>
            <slot name="inputlabel"></slot>`;
      }
  });
</script>
<my-element>
  <input disabled id="input1" type="text" slot="inputel"/>
  <label for="input1" slot="inputlabel">label</label>
</my-element>

【问题讨论】:

  • 你能添加完整的 HTML,最好是一个工作的 SO sn-p。 inputlabel 在哪里?
  • @Danny'365CSI'Engelman 添加。
  • @lamplightdev 不是真的,但它肯定有一些有趣的见解,谢谢你的链接!

标签: css web-component shadow-dom custom-element


【解决方案1】:

完整详解在:::slotted CSS selector for nested children in shadowDOM slot


<my-element>
  <input disabled id="input1" type="text" slot="inputel"/>
  <label for="input1" slot="inputlabel">label</label>
</my-element>

ShadowDOM SLOTs 关闭

inputlabellightDOM 中,
并在反射(未移动!)到 shadowDOM 时保持不可见 SLOTs

所以你必须在 lightDOM 中设置它们的样式:

    <style>
      /* style lightDOM!! */
      my-element input:disabled ~ label {
        color: red;
      }
    </style>

<template id="MY-ELEMENT">
  <style>
    ::slotted(input:disabled){
      border:1px dashed red;
    }
  </style>
INPUT <slot name="inputElement"></slot> <slot name="inputLabel"></slot>
</template>
<script>
  customElements.define('my-element', class extends HTMLElement {
    constructor() {
      super().attachShadow({mode: 'open'})
             .append(document.getElementById(this.nodeName).content.cloneNode(true));
      }
  });
</script>
<style>
  /* style lightDOM!! */
  my-element input:disabled ~ label {
    color: red;
    font-weight: bold;
  }
</style>
<my-element>
  <input disabled id="inp1" placeholder="This is disabled" type="text" slot="inputElement"/>
  <label for="inp1" slot="inputLabel">input label 1</label>
</my-element>
<br>
<my-element>
  <input id="inp2" placeholder="Not disabled" type="text" slot="inputElement"/>
  <label for="inp2" slot="inputLabel">input label 2</label>
</my-element>

这个用例有点做作,my-element没有任何收获,用户仍然需要声明inputlabel

也许创建一个&lt;input-element type="text" label="A Label"&gt; 来创建上面的 HTML,然后在其 shadowDOM 中拥有禁用的 CSS(不需要 SLOT)

或(伪代码)

<template id="INPUT-ELEMENT">
  <style>
    input:disabled~label{
      color:red;
    }
  </style>
  <input id="i"/>
  <label for="i"><slot name="label"></slot></label>
</template>

...
connectedCallback(){
  let inp=this.shadowRoot.querySelector("input");
  inp.type = this.getAttribute("type");
  inp.toggleAttribute( "disabled" , this.hasAttribute("disabled"));
}


<input-element type="text" disabled>
  <span slot="label"><b>Fancy Label<b></slot>
</input-element>

如果你想给用户更多的控制权


::slotted 在其前身在 V0 中引起性能问题后,被纳入 WebComponents V1 规范
因此它只接受简单的选择器作为参数,并且只能对插槽中的第一级元素进行样式化

所以在上面的例子中::slotted 可以设置&lt;span slot="label"&gt; 的样式,但不能设置&lt;b&gt; 的样式。

注意:SLOTs 是 LIVE 连接,您可以随时重新应用 CSS,内容更改会立即反映到 shadowDOM:

document.querySelector("input-element &gt; b").innerHTML="Better Label!";


更多 SLOT 相关答案可以通过 StackOverflow 搜索找到:Custom Elements SLOTs

【讨论】:

  • 感谢您的宝贵时间,但这正是我试图避免的。我认为覆盖原生元素和/或将原生元素包含在 shadow dom 中没有任何意义。在客户端为它们设置样式是一个选项,但我无法控制它,因为此组件在库中导出,并且用户应该只传递输入和标签元素,库应该处理样式。
  • 那个'无控制'然后包括输入和标签标签的放置,您的用户可以在输入之前放置标签..然后使用float:right显示它在输入之后..
猜你喜欢
  • 2021-09-10
  • 2021-08-28
  • 1970-01-01
  • 2017-03-23
  • 1970-01-01
  • 2023-03-12
  • 2012-12-27
  • 2018-02-01
相关资源
最近更新 更多