有没有办法改变阴影元素中的样式?具体来说,扩展/覆盖在css类中找到的一些属性?我正在使用名为Beanote的chrome扩展程序,自2017年4月(2017年)以来尚未更新,我想修复一个讨厌的错误。我发现一行css补丁对我来说足够了,但是我不知道如何应用它而不进入阴影元素本身并直接在开发工具中编辑这些样式。
我正在寻找一种方法:
/*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
有关,如果它的意思是,它不适用于我的需要或::shadow
不推荐使用的功能。
由于样式的隔离(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'
时它才会起作用。
2019年Chrome 73+和Opera 60+的更新
现在可以直接实例化CSSStyleSheet对象并将其影响到Shadow DOM或文档:
var sheet = new CSSStyleSheet
sheet.replaceSync( `.color { color: pink }`)
host.shadowRoot.adoptedStyleSheets = [ sheet ]
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函数。
扩展以前的答案。
外部样式总是胜过Shadow DOM中定义的样式,即当您添加引用正在样式化的组件的全局样式规则时。见:https://developers.google.com/web/fundamentals/web-components/shadowdom#stylefromoutside
否则,这将取决于元素shadow DOM是否嵌入了styleSheet
,或者它是否采用了使用adoptedStyleSheets
的样式表。
如果元素嵌入在元素中,则可以使用addRule
或insertRule
向现有样式表添加或插入规则。这也适用于添加了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];
我想在其中一条评论中回答@Renato给出的答案,因为它指出了解决从托管应用程序定制WebComponent问题的好的恕我直言。
@Supersharp是正确的,外部CSS规则没有传播到Shadow Root,这是设计的。
CSS变量是一个很好的方向,但从我个人的经验来看,单个用法的价值有点过分,是的,它们必须得到WebComponent的支持。
通过继承传播:host
属性(正如@Renato提到的那样)是,恕我直言,与API设计一致的完美正确的模式:
:host
)的CSS规则是外部规则可以覆盖的设计:host
的子项,Shadow DOM的内部内容,可以默认或通过显式规则继承:host
的CSS规则 - 这也是设计我会说,在适用的情况下,在考虑CSS样式表注入之前最好采用这种方法,并且也不会受到open
模式的限制。
当然,这种方法在以下情况下无济于事:
:host
的相关规则然而,再次根据我自己的经验,具有理想的可覆盖CSS规则的简单组件可以从通过:host
传播规则的非侵入模式中获益很多。