CSS 阴影优先 DOM <style>

CSS precendence in shadow DOM <style>

CSS 优先级规则对影子 DOM 中的 <style> 标签有何规定?

我有一个元素 <component class="component">,CSS 文件包含在 <head> 中,其中:

component {
    display: inline-block;
}

和一个 <style> 标签在一些阴影 DOM 内,其中:

::slotted(.component) {
    display: block;
}

如果我理解正确,第一条规则应该具有 0.0.1 的特异性,因为它有一个元素,第二条规则应该具有 0.1.1 的特异性,因为它有一个伪元素和一个 class.因此,第二个更具体,应该覆盖第一个。但这不会发生。在开发人员的控制台 (Chrome) 中,我看到了两条规则,但都没有被划掉,在 "computed styles" 面板中,我看到了 'display: inline-block'.

评论中要求的更详细的示例:

<head>
    <style>
        /* "other-component" related styles: */
        other-component {
            display: inline-block;
        }
    </style>
</head>
<body>
    <some-component>
        #shadow-root:
            <style>
                slot[name=some-slot]::slotted(*) {
                    display: block; /* Only works with !important. */
                }
            </style>
            <slot name="some-slot"></slot>
        <!-- The actual ("light-dom") content: -->
        <other-component slot="some-slot"></other-component>
    </some-component>
</body>

此行为在 CSS Scoping Module Level 1 Draft §3.3:

中定义

When comparing two declarations that have different tree contexts, then for normal rules the declaration earlier in the shadow-including tree order [the first, global rule] wins, and for important rules the declaration coming later in the shadow-including tree [the second, ::slotted(*) rule] order wins.

Note: This is the opposite of how scoped styles work.

other worlds中:

Styles that applied before distribution continue to apply after distribution.

我们可能在 https://github.com/w3c/csswg-drafts/issues/2290#issuecomment-382465643

处对设计有最多 in-depth 的解释

A few reasons went into the current design:

We purposely didn't involve specificity at all. Doing so would expose implementation details of the component, which makes code fragile - if the component is updated and changes the exact selector it uses, it might start overriding outside rules that previously won, or vice versa, and there's no good way for the component's user to understand or manipulate this.

So we have to decide in some other way. Document order (the final cascade step) doesn't really work here - it adds an unexpected dependency on exactly how you load the custom element, and might have interesting race

So we're left with Cascade Origin, or something close to it, that just unreservedly makes one or the other win. Actually injecting a new origin into the list didn't seem like a great idea; it's unclear how user vs author stylesheets should interact with this. So instead we add another cascade step for this.

And finally, we have to make a decision about which wins. We already know that whatever order we choose, !important should have the reverse order; this is how the cascade origins already work. So we have to decide whether the outer page wins by default, but the component wins in !important, or the reverse. We decided that the former made more sense; this means that the component author's normal styles are "defaults", the component user's styles (!important or not) can override that, and the component author's !important styles can be used to "lock down" styles that need to stay how they are. Going the other way around didn't seem to satisfy use-cases as well: it would mean that component users can't override styles by default; they'd have to use !important to do so, possibly interfering with their other styles; and then component authors would have no way of "locking down" styles.