css 从外部阴影DOM样式

rn0zuynd  于 2023-04-08  发布在  其他
关注(0)|答案(4)|浏览(199)

我正在寻找一种从外部对shadow DOM进行样式化的方法。例如,我想将所有'span.special'元素中的所有文本的颜色设置为RED。包括shadow DOM中的'span.special'元素。我如何才能做到这一点?
以前有**::shadow伪元素和/deep/combinator aka〉〉〉**用于此目的。

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

但是现在**::shadow**、**/deep/〉〉**都被弃用了。那么,我们有什么可以替代它们呢?

uqzxnwby

uqzxnwby1#

我确实尝试了很多方法,包括这里描述的那些。因为我使用的是外部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");
  });
nkoocmlb

nkoocmlb2#

仍然没有简单的方法来穿透影子根,但这里有3种方法可以做到这一点。只要记住,你需要在Web组件内部进行更改。
1.使用变量v1-您需要在Web组件中传递属性并使用变量。
1.使用变量v2-您需要在Web组件内部使用变量。
1.使用::part()-您需要在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() */
custom-container-c::part(paragraph) {
  color: magenta;
}
<p>Light content</p>
<custom-container-a border></custom-container-a>
<custom-container-b></custom-container-b>
<custom-container-c></custom-container-c>
nzk0hqpo

nzk0hqpo3#

您可以使用@import css,如answer中所解释的,以解决SO上的另一个问题。
将规则包含在 shadow tree 中的 style 元素内。

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

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

fcg9iug3

fcg9iug34#

好吧,如果你正在使用你不能改变的库Web组件,@import不是一个解决方案。
最后,我找到了几种方法:
1)层叠。Shadow DOM的主元素的样式也会影响Shadow DOM元素。如果你需要样式化Shadow DOM的特定元素,这不是一个选项,不是每个。
2)自定义属性https://www.polymer-project.org/1.0/docs/devguide/styling如果Web组件的作者提供了此类属性。
3)在Polymer中,也有自定义混合https://www.polymer-project.org/1.0/docs/devguide/styling
4)@import,但仅适用于非库组件
所以,有几种可能性,但它们都是有限的。没有足够强大的方式来外部造型为::shadow。

相关问题