轻量 DOM 样式泄漏到 Shadow DOM 中

13

我正在尝试创建一个带有浮动小部件的Chrome扩展程序。为此,我必须将元素与页面其余部分隔离开来。影子DOM看起来非常适合,但它并没有做我期望的事情。

这是我的内容脚本:

content.js

var lightDom = document.createElement('style');
lightDom.innerText = 'div { color: red }';

document.body.appendChild(lightDom);

var shadowDom = document.createElement('div');

document.body.appendChild(shadowDom);

var shadowRoot = shadowDom.attachShadow({'mode': 'open'});

shadowRoot.innerHTML = `
    <style>
        div {
            background-color: blue;
        }
    </style>
    <div>Shadow!</div>
`;
在Shadow DOM中的div应该是黑色文本,但实际上却是红色文本。我做错了什么吗?
1个回答

17

为什么会出现这种情况?

在 Light DOM 中,CSS 选择器无法访问 shadow DOM 内部的元素。但是当某个 CSS 属性具有 inherit 值时(color 的默认值即为此),shadow DOM 仍然会从 Light DOM 中继承它们。

摘自 CSS Scoping 规范

3.3.2 继承
Shadow tree 的顶级元素从其 host 元素继承。分发列表中的元素从它们最终分配到的内容元素的父元素而不是正常父元素中继承。

如何防止这种情况发生?

你可以使用 initial 值来阻止属性值的继承。

摘自 CSS 级联与继承规范

7.3.1. 重置属性:initial 关键字
如果层叠值是 initial 关键字,则该属性的初始值将成为其指定值。

每个属性的初始值在其定义所述的规范中有记录。 colorCSS Color 规范 中有记录,其初始值为 depends on user agent,对于大多数用户代理来说这将是 black

你可以将 initial 分配给你不想继承其值的每个属性。或者你可以将 all 的值设置为 initial,像这样:

.selector 
{
    all: initial;
}

在与初始关键字相同的规范中,all 属性定义如下:

3.1. 重置所有属性:all 属性
all 属性是一个简写属性,可重置除了 direction 和 unicode-bidi 以外的所有 CSS 属性。它仅接受 CSS-wide 关键字。

"CSS-wide 关键字" 在 CSS 3 值规范 中的 3.1.1 节中定义,但其实际上只包括 initialinheritunset 这些值。


谢谢你的回答!我在我的shadowDom样式中添加了all: initial以防止这种情况发生。也许你可以把这个作为建议加入到你的回答中。 - Božo Stojković
吹毛求疵:*inherit [...] 是 color 的默认值* - 我认为这不准确。MDN说:“CSS 属性的初始值是其定义表中列出的默认值。”,而定义表则说明 color 的初始值取决于浏览器。 - OfirD
@HeyJude 定义表确实是这么说的。但它也说它是继承的。这意味着对于除根元素以外的所有元素,值将为 inherit。根元素的颜色取决于浏览器。这也是我测试后在浏览器中遇到的行为。 - Wazner

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