覆盖影子根元素中的样式
Override styles in a shadow-root element
有没有办法改变阴影元素中的样式?具体来说,extend/overwrite 在 css class?我正在使用一个名为 Beanote 的 chrome-extension,它自 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 变量是可能的,但它们应该在隐藏组件中显式实现(这不是第 3 方库的情况)。
解决方法是直接在阴影中注入样式线 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 对象并将其影响到阴影 DOM 或文档:
var sheet = new CSSStyleSheet
sheet.replaceSync( `.color { color: pink }`)
host.shadowRoot.adoptedStyleSheets = [ sheet ]
Ionic V4 select 向下图标颜色变化示例
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 函数。
扩展之前的答案。
外部样式总是胜过影子 DOM 中定义的样式,即当您添加引用您正在设置样式的组件的全局样式规则时。参见:https://developers.google.com/web/fundamentals/web-components/shadowdom#stylefromoutside
否则这将取决于元素阴影 DOM 是否嵌入了 styleSheet
,或者它是否采用 style-sheet 使用 adoptedStyleSheets
.
如果元素嵌入到元素中,您可以使用 addRule
或 insertRule
向现有 style-sheet 添加或插入规则。这也适用于添加 adopedStyleSheets
.
的 style-sheets
如前一个答案所述,您可以将新的 style-sheet 添加到已采用的 style-sheet 列表中。这在 shadowRoot 包含嵌入的 styleSheet
时也有效,因为 adoptedStyleSheets
优先,而 styleSheetList
是 read-only 属性.
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 up-front 支持.
通过 继承 通过 :host
传播 属性(正如@Renato 提到的那样)是,恕我直言,完美正确的图案与 API 设计对齐:
- 自定义元素的 (
:host
) CSS 规则在设计上可被外部规则覆盖
:host
的children,阴影DOM的内部内容,可以默认继承:host
的CSS规则或者通过明确的规则 - 这也是设计
我想说,在适用的情况下,最好在考虑 CSS 样式表注入之前采用这种方法,并且也不会受到仅 open
模式的限制。
当然,这种方法在以下情况下无济于事:
- 内部元素没有从
:host
继承相关规则
- WebComponent 的结构相当复杂,所以单独
:host
根本帮不上忙
然而,再次根据我自己的经验,具有理想的可覆盖 CSS 规则的简单组件可能会从通过 :host
.
传播规则的 non-intrusive 模式中受益匪浅
有没有办法改变阴影元素中的样式?具体来说,extend/overwrite 在 css class?我正在使用一个名为 Beanote 的 chrome-extension,它自 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 变量是可能的,但它们应该在隐藏组件中显式实现(这不是第 3 方库的情况)。
解决方法是直接在阴影中注入样式线 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 对象并将其影响到阴影 DOM 或文档:
var sheet = new CSSStyleSheet
sheet.replaceSync( `.color { color: pink }`)
host.shadowRoot.adoptedStyleSheets = [ sheet ]
Ionic V4 select 向下图标颜色变化示例
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 函数。
扩展之前的答案。
外部样式总是胜过影子 DOM 中定义的样式,即当您添加引用您正在设置样式的组件的全局样式规则时。参见:https://developers.google.com/web/fundamentals/web-components/shadowdom#stylefromoutside
否则这将取决于元素阴影 DOM 是否嵌入了 styleSheet
,或者它是否采用 style-sheet 使用 adoptedStyleSheets
.
如果元素嵌入到元素中,您可以使用 addRule
或 insertRule
向现有 style-sheet 添加或插入规则。这也适用于添加 adopedStyleSheets
.
如前一个答案所述,您可以将新的 style-sheet 添加到已采用的 style-sheet 列表中。这在 shadowRoot 包含嵌入的 styleSheet
时也有效,因为 adoptedStyleSheets
优先,而 styleSheetList
是 read-only 属性.
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 up-front 支持.
通过 继承 通过 :host
传播 属性(正如@Renato 提到的那样)是,恕我直言,完美正确的图案与 API 设计对齐:
- 自定义元素的 (
:host
) CSS 规则在设计上可被外部规则覆盖 :host
的children,阴影DOM的内部内容,可以默认继承:host
的CSS规则或者通过明确的规则 - 这也是设计
我想说,在适用的情况下,最好在考虑 CSS 样式表注入之前采用这种方法,并且也不会受到仅 open
模式的限制。
当然,这种方法在以下情况下无济于事:
- 内部元素没有从
:host
继承相关规则
- WebComponent 的结构相当复杂,所以单独
:host
根本帮不上忙
然而,再次根据我自己的经验,具有理想的可覆盖 CSS 规则的简单组件可能会从通过 :host
.