从外面影子DOM样式

时间:2016-05-20 17:34:13

标签: javascript css html5 styling shadow-dom

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

此前,为此目的, :: shadow 伪元素和 / deep / 组合器又名>>> 。所以我可以写点像

span.special, *::shadow span.special {
    color: red
}

但现在不推荐使用 :: shadow / deep / >>> 。那么,我们有什么替代它们?

4 个答案:

答案 0 :(得分:4)

你可以使用@ answer中解释的@import css来解决另一个关于SO的问题。

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

 <style>
   @import url( '/css/external-styles.css' )
 </style>

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

答案 1 :(得分:4)

嗯,如果您正在使用无法更改的库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 are。

答案 2 :(得分:1)

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

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

这不是最佳的解决方案,不适合大型样式,但是对于小巧的外观确实有效。

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

  import { toastController } from '@ionic/core';

  let toastOpts = {
    message: "Some message goes here.",
    cssClass: "toast-with-vertical-buttons",
    buttons: [
      {
        text: "Button 1",
        side: 'end'
      },
      {  
        text: "Button2",
        side: 'end'
      },
      {
        icon: "close",
        side: "start"
      }
    ]
  }
  toastController.create(toastOpts).then(async p => {
    let toast = await p.present(); // this renders ion-toast component and returns HTMLIonToastElement
    toast.shadowRoot.querySelector('div.toast-button-group-end').setAttribute("style", "flex-direction: column");
  });

答案 3 :(得分:1)

仍然没有简单的方法可以刺穿阴影根部,但您可以通过以下 3 种方法进行操作。请记住,您需要在 Web 组件内部进行更改。

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

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

  3. 使用 struct Message: Decodable { let command: String let data: String } - 您需要向要在 Web 组件中设置样式的元素添加部件属性。 (注意:这个伪元素得到了很好的支持,但仍处于实验模式,所以在生产中使用它之前请确保你知道这一点)。

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

::part()
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>'
/* 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() NOTE: The specs for this hasn't been finalized.
So it might not be a good idea to use in production. */
custom-container-c::part(paragraph) {
  color: magenta;
}