Shadow Dom继承父页面CSS [Chrome]

13

我所阅读的所有信息都表明,Shadow DOM应该是受其父页面CSS保护的。也就是说,如果我将所有div样式设置成紫色字体:

<style>
  div{color: purple}
</style>

我的Shadow DOM中的div应该具有浏览器默认颜色。

我正在编写一个Chrome扩展程序,将HTML注入到任何给定的页面中。除非这个HTML受到Shadow Dom或Iframe的保护,否则它将继承页面的所有CSS。

在这个问题中解决这个问题的建议是使用Shadow Dom。因此,我实施了一种解决方案,但注意到它仍然继承了页面的CSS。我认为这可能是在Chrome扩展程序中使用它时出现的问题,所以我从一些Shadow Dom示例中劫持了一个jsBin(并将其放入另一个实时编码应用程序中以确保)。

https://codepen.io/hyrumwhite/pen/xPRexQ

结果相同。我的shadow DOM继承了页面CSS,并且我的div(和奇怪的h1)是紫色的。

看起来Shadow Dom中的子元素会继承应用于宿主元素的任何样式。

这是设计上的工作方式吗?有没有办法阻止这种情况?还是说Shadow DOM足够新,这是一个错误,我应该期望在继续使用它时出现类似的错误?


2
继承和选择器之间有区别。如果我没记错,阴影边界只影响选择器可见性,但所有被继承的东西都会受到影响。https://www.polymer-project.org/2.0/docs/devguide/style-shadow-dom#use-inheritance-from-document-level-styles https://css-tricks.com/playing-shadow-dom/ - Josh Lee
@JoshLee 有道理。在这种情况下使用 Shadow DOM 似乎不是最好的选择。 - SethWhite
2个回答

14

对于我来说,在 ShadowDOM 样式内部添加 :host { all: initial } 作为第一条 CSS 规则可以防止继承,并且不会影响 ShadowDOM 内定义的其他 CSS。

使用 * { all: initial } 太过宽泛,覆盖了我在 ShadowDOM 中定义的大部分 CSS。

参考文献:WebFundamentals 项目ShadowDOM 文档中标记为 #reset 的部分。


更加高级、易读的页面:https://developers.google.com/web/fundamentals/web-components/shadowdom#reset - danguilherme
1
我建议避免使用:host选择器,因为它可能会被Light DOM CSS覆盖。 - CITguy

13
继承属性将像往常一样被继承。最好将阴影边界视为影响级联的范围,即选择器的范围和规则的重要性。
为了将阴影内容与页面隔离开,请考虑使用all属性

document.getElementById("example_control").attachShadow({mode:'open'}).innerHTML=`
  <h1>shadow dom header</h1>
  <div>shadow dom div</div>`;
document.getElementById("example_initial").attachShadow({mode:'open'}).innerHTML=`
  <style>*{all:initial}</style>
  <h1>shadow dom header</h1>
  <div>shadow dom div</div>`;
document.getElementById("example_unset").attachShadow({mode:'open'}).innerHTML=`
  <style>*{all:unset}</style>
  <h1>shadow dom header</h1>
  <div>shadow dom div</div>`;
div{color:purple}
div{border:1px solid}
<p>control:
<div id=example_control></div>

<p>initial:
<div id=example_initial></div>

<p>unset
<div id=example_unset></div>


1
这个例子比我想象的要好得多:阴影内容中的div继承了color属性,但没有继承border属性。 - Josh Lee
1
你可以考虑将所有的 Shadow DOM 内容都包裹在一个根元素中(例如 <div id="root">... shadow markup here ...</div>),而不是使用 splat。这样,你就可以通过定位 #root 来有意识地打破级联。 - CITguy
可以在这个答案中找到关于为什么阴影内容内部的div继承了color属性但没有继承border的详细解释。 - OfirD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接