覆盖shadow-root元素中的样式

时间:2017-12-04 00:49:12

标签: css web-component shadow-dom

有没有办法改变阴影元素中找到的样式?具体来说,扩展/覆盖在css 中找到的一些属性?我正在使用名为Beanote的Chrome扩展程序,该扩展程序自2017年4月(2017年)以来尚未更新,并且我还想修复一个讨厌的错误。我发现一行css补丁对我来说足够了,但是我不知道如何应用它而不进入阴影元素本身并直接在开发工具中编辑这些样式。

我正在寻找一种方法:

//main method:
public static void main(String[] args){
   test(new int[]{1, 2, 5, 12, 2}, 4, 5);
}

覆盖此内容:

/*global css rule*/
.the-class-name { property-name: my-value; }


我在网上找到的涉及/* style tag inside the shadow-root */ .the-class-name { property-name: bad-value; } shadow-root override style的查询的大多数资源都与edit shadow-root styling有关,如果它的意思是,它不起作用我的需求或弃用的功能,如:host

4 个答案:

答案 0 :(得分:10)

由于样式的隔离(Shadow DOM的一个功能),您无法定义将在Shadow DOM范围中应用的全局CSS规则。

可以使用CSS变量,但它们应该在阴影组件中显式实现(与第三方库不同)。

解决方法是直接在shadow DOM中注入样式行。

//host is the element that holds the shadow root:
var style = document.createElement( 'style' )
style.innerHTML = '.the-class-name { property-name: my-value; }'
host.shadowRoot.appendChild( style )

注意:仅当Shadow DOM mode设置为'open'时,它才有效。

针对Chrome 73+和Opera 60 +的2019更新

现在可以直接实例化CSSStyleSheet对象并将其影响到Shadow DOM或文档:

var sheet = new CSSStyleSheet
sheet.replaceSync( `.color { color: pink }`)
host.shadowRoot.adoptedStyleSheets = [ sheet ] 

答案 1 :(得分:2)

Ionic V4选择向下图标的颜色更改示例

document.querySelector('#my-select').shadowRoot.querySelector('.select-icon-inner').setAttribute('style', 'opacity:1');


ionViewDidEnter() {
    document.querySelector('#my-select').shadowRoot.querySelector('.select-icon-inner').setAttribute('style', 'opacity:1');
  }

如果要覆盖默认生成的shadowRoot样式,则必须在页面完全加载后调用js函数。

答案 2 :(得分:1)

扩展先前的答案。

外部样式始终会胜过Shadow DOM中定义的样式,即,当您添加引用要样式化的组件的全局样式规则时。参见:https://developers.google.com/web/fundamentals/web-components/shadowdom#stylefromoutside

否则,这将取决于是否将影子Shadow DOM嵌入到styleSheet中,或者它是否使用了adoptedStyleSheets使用样式表。

如果该元素已嵌入元素中,则可以使用addRuleinsertRule向现有样式表中添加或插入规则。这也适用于添加了adopedStyleSheets的样式表。

如上一个答案所述,您可以将新的样式表附加到已采用的样式表列表中。当shadowRoot包含嵌入式styleSheet时,这也适用,因为adoptedStyleSheets优先,并且styleSheetList是只读属性。

assert(myElement.shadowRoot.styleSheets.length != 0);
myElement.shadowRoot.styleSheets[0].addRule(':host', 'display: none;');

assert(myElement.shadowRoot.adoptedStyleSheets.length != 0);
`myElement.shadowRoot.adoptedStyleSheets[0].addRule(':host', 'display: none;');`

const sheet = new CSSStyleSheet();
sheet.replaceSync(`:host { display: none; }`);

const elemStyleSheets = myElement.shadowRoot.adoptedStyleSheets;

// Append your style to the existing style sheet.
myElement.shadowRoot.adoptedStyleSheets = [...elemStyleSheets, sheet];

// Or if just overwriting a style set in the embedded `styleSheet`
myElement.shadowRoot.adoptedStyleSheets = [sheet];

答案 3 :(得分:0)

我想在评论之一中附上@Renato给出的答案,因为它指出了一种很好的恕我直言的方法,可以解决从托管应用程序自定义WebComponent的问题。

@Supersharp实际上是正确的,外部CSS规则不是不是传播到Shadow Root中的,这是设计使然。

CSS变量是一个很好的方向,但是从我个人的经验来看,对于单一用法的价值有点过高,而且是的,必须在WebComponent的前面就支持它们。

恕我直言,

通过{strong>继承(恰好是@Renato提到)通过:host传播属性,恕我直言,这与API设计完全吻合:

  • 根据设计,自定义元素(:host)的CSS规则可以被外部规则覆盖
  • :host的子级(Shadow DOM的内部内容)可以默认或显式地继承:host的CSS规则-设计上也是如此

我会说,在适用的情况下,最好在考虑CSS样式表注入之前采用这种方法,并且也不会仅受open模式的限制。

当然,这种方法在以下情况下无济于事:

  • 内部元素没有继承:host的相关规则
  • WebComponent的结构非常复杂,因此单个:host根本无法帮助他们全部

根据我的经验,具有可重写的CSS规则的简单组件可能会受益于通过:host传播规则的非侵入式模式。