从外面影子DOM样式

Oka*_*ngo 11 javascript css html5 styling shadow-dom

我正在寻找一种从外部设计阴影DOM的方法.例如,我想将所有'span.special'元素中所有文本的颜色设置为RED.包括来自shadow DOM的'span.special'元素.我怎么能这样做?

以前为此目的有:: shadow伪元素和/ deep / combinator aka >>>.所以我可以写一些像

span.special, *::shadow span.special {
    color: red
}
Run Code Online (Sandbox Code Playgroud)

但是现在:: shadow,/ deep />>>已被弃用.那么,我们有什么替代它们?

Gen*_*ano 13

仍然没有简单的方法可以刺穿影子根,但这里有 3 种方法可以帮助你。请记住,您需要在 Web 组件内进行更改。

  1. 使用变量 v1 - 您需要传递属性并使用 Web 组件内的变量。

  2. 使用变量 v2 - 您将需要使用 Web 组件内的变量。

  3. 使用::part()- 您需要向要在 Web 组件中设置样式的元素添加部件属性。(注意:这个伪元素得到了很好的支持,但仍处于实验模式,因此在生产中使用它之前请确保您了解这一点)。

运行下面的代码示例以了解详细信息。

const elA = document.querySelector('custom-container-a');
const shadowRootA = elA.attachShadow({mode:'open'});
shadowRootA.innerHTML = '<style>:host([border]) {display:block;border: var(--custom-border);}</style>'+
    '<p>Shadow content A</p>'
  
  
const elB = document.querySelector('custom-container-b');
const shadowRootB = elB.attachShadow({mode:'open'});
shadowRootB.innerHTML = '<style>p {display:block;color: var(--custom-color, blue);}</style>'+
    '<p>Shadow content B</p>'


const elC = document.querySelector('custom-container-c');
const shadowRootC = elC.attachShadow({mode:'open'});
shadowRootC.innerHTML = '<p part="paragraph">Shadow content C</p>'
Run Code Online (Sandbox Code Playgroud)
/* Normal way of styling */
p {
  color: orange;
}

/* Using variables version 1 */
custom-container-a {
  --custom-border: 3px solid gold;
}

/* Using variables version 2 */
custom-container-b {
  --custom-color: green;
}


/* Using ::part() */
custom-container-c::part(paragraph) {
  color: magenta;
}
Run Code Online (Sandbox Code Playgroud)
<p>Light content</p>
<custom-container-a border></custom-container-a>
<custom-container-b></custom-container-b>
<custom-container-c></custom-container-c>
Run Code Online (Sandbox Code Playgroud)

  • 阴影部分现在得到了很好的支持:https://caniuse.com/mdn-css_selectors_part (4认同)

Sup*_*arp 6

您可以使用@import css,如this answer to another question on SO中所述。

将规则包含在阴影树中style元素中。

 <style>
   @import url( '/css/external-styles.css' )
 </style>
Run Code Online (Sandbox Code Playgroud)

请注意,>>>组合器仍然是 CSS 范围模块草案的一部分。


Bru*_*olo 6

我确实尝试了很多方法,包括这里描述的方法。由于我使用的是外部 Web 组件库,因此我无权修改这些组件。因此,对我有用的唯一解决方案是使用 JS querySelector,如下所示:

document.querySelector("the-element.with-shadow-dom")
  .shadowRoot.querySelector(".some-selector").setAttribute("style", "color: black");
Run Code Online (Sandbox Code Playgroud)

不是最好的解决方案,不适合大型样式,但确实适用于小装饰。

@John 这已经用 Chrome 83.0.4103.116 测试过(仍将在 Safari 中测试),我为 Ionic (v5)ion-toast组件做了测试。这是我使用的(几乎)真实代码:

document.querySelector("the-element.with-shadow-dom")
  .shadowRoot.querySelector(".some-selector").setAttribute("style", "color: black");
Run Code Online (Sandbox Code Playgroud)


Oka*_*ngo 5

好吧,如果您正在使用无法更改的库Web组件,则@import不是解决方案。

最终,我找到了几种方法:

1)级联。Shadow DOM的宿主元素的样式也会影响Shadow DOM元素。如果您需要设置Shadow DOM的特定元素(不是每个元素)的样式,则不是一种选择。

2)自定义属性https://www.polymer-project.org/1.0/docs/devguide/styling 如果Web组件的作者提供了此属性。

3)在Polymer中,也具有Custom Mixins https://www.polymer-project.org/1.0/docs/devguide/styling

4)@import,但仅适用于非库组件

因此,有几种可能性,但是所有可能性都是有限的。没有比:: shadow强大的外部样式方法。