在 Shadow DOM 中为子元素设置样式

14

我正在尝试为一个影子DOM根元素的子元素设置样式。
这定义了一个名为element-el的自定义元素,其中有一个名为“x”的类命名为的元素,其中包含字母x,我想将其设置为红色。

class El extends HTMLElement {
    constructor() {
        super();
        var shadow = this.attachShadow({mode:'open'});
        shadow.innerHTML = '<span class="x">X</span>';
    }
}
customElements.define ('element-el',El);

我已经尝试了这些 CSS 样式:

element-el::slotted(.x) {
  color:red;
}
element-el::host .x {
  color:red;
}
element-el:host .x {
  color:red;
}
element-el::shadow .x {
  color:red;
}
element-el /deep/ .x {
  color: red;
}
element-el::content .x {
  color:red;
}

X不会变成红色。我正在使用Chrome 56,它应该支持此操作...

我想在不将样式元素放入影子DOM中的情况下进行样式设置。
这是一个Codepen示例: http://codepen.io/anon/pen/OpRLVG?editors=1111

编辑:
这篇文章表明,从外部CSS文件中设置样式可以影响到shadow children - 他们可能是错的吗?


对于Angular 4.3.0及以上 (Angular 12.x),请参阅:如何从父组件样式化子组件? - Top-Master
3个回答

1
显然,问题在于您试图使用全局CSS来为影子树元素设置样式。
您可以使用:host伪选择器,但是为了这样做,您必须将样式放置在影子树内容中。
请在您的JavaScript中进行以下更改:
class El extends HTMLElement {

    constructor() {
        super();
        var shadow = this.attachShadow({mode:'open'});
        var innerHTML = '';
        innerHTML += '<style>';
        innerHTML += ':host(element-el.red) span {color: red}';
        innerHTML += ':host(element-el.green) span {color: green}';
        innerHTML += ':host(element-el.blue) span {color: blue}';
        innerHTML += '</style>';      
        innerHTML += '<span class="x">X</span>';      
        shadow.innerHTML = innerHTML;
    }

}

customElements.define ('element-el',El);

请在您的更新的codepen中检查一个功能性示例。


谢谢您的回答。我之前参考了这个链接:https://developer.mozilla.org/en-US/docs/Web/Web_Components/Custom_Elements,认为可以从外部CSS样式文件中修改影子DOM子元素的样式(请参见“示例”部分中的“CSS文件”)- 那么他们在文章中是错误的吗? - Yuval A.
请查看他们在以下网址提供的示例:https://mdn.mozillademos.org/en-US/docs/Web/Web_Components/Custom_Elements$samples/Example。在Chrome浏览器中,使用伪选择器`::slotted`的两个CSS声明都无法正常工作。 - Romulo

0
一个简单的解决方案是在Shadow DOM中定义x类:

class El extends HTMLElement {
    constructor() {
        super()
        this.attachShadow({mode:'open'})
            .innerHTML = `
               <style>
                  .x { color: red } 
               </style>
               <span class="x">X</span>`
    }
}
customElements.define ('element-el',El)
<element-el></element-el>

注意:由于 Shadow DOM 的样式封装,无论是使用 Romulo 的 :host 解决方案、直接类声明(见上文)还是 外部样式表,您都需要在 Shadow DOM 中放置一个 <style> 元素。

当然,如果您使用了继承的 CSS 属性(如 color),它将适用于所有的 Shadow DOM 内容,您可以使用普通的 CSS:

class El extends HTMLElement {
    constructor() {
        super();
        var shadow = this.attachShadow({mode:'open'});
        shadow.innerHTML = '<span class="x">X</span>';
    }
}
customElements.define ('element-el',El);
element-el {
    color: red;
}
<element-el></element-el>   


谢谢您的回答。我之前参考了这个链接:https://developer.mozilla.org/en-US/docs/Web/Web_Components/Custom_Elements,认为可以从外部CSS样式文件中修改影子DOM子元素的样式(请参见“示例”部分中的“CSS文件”)- 那么他们在文章中是错误的吗? - Yuval A.
2
@YuvalA。是的,他们在::slotted样式方面是错误的。它们不起作用,因为它们不在正确的位置(即在影子DOM的<style>元素中)。 - Supersharp

-1
这可能会对处于类似情况的其他人有所帮助。
在我的情况下,我有:
<svg class="icon">
    <use xlink:href="#my-icon"></use>
</svg>

要访问#shadow-root中呈现的图标,我使用:

.icon use {
  fill: #f80;
}

2
这与什么相关? - ADJenks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接