这让我困惑了一阵子,所以趁着记忆犹新,我把它写下来。仅仅因为您使用的是 Web 组件,并不意味着它的样式完全是孤立的。Web 组件中可能包含与网站其余部分一样正常样式化的内容。 就像这样
查看 CodePen:具有全局样式的 Web 组件(因为没有 Shadow DOM),作者 Chris Coyier (@chriscoyier) 在 CodePen 上。
该 <whats-up>
元素通过将点击处理程序附加到其内部的 <button>
来隔离其 JavaScript 驱动的功能。但是,该按钮的样式来自应用于该页面的 全局 CSS。
将模板移到 Web 组件内部
但假设我们将该 <button>
移到 Web 组件中,以便我们可以单独使用 <whats-up>
。我们可以通过 .innerHTML
‘ing 自定义元素来做到这一点
查看 CodePen:具有全局样式的 Web 组件(因为没有 Shadow DOM),作者 Chris Coyier (@chriscoyier) 在 CodePen 上。
同样,完全由全局 CSS 样式化。酷。这可能是可取的。它也可能不可取。也许您正在寻找 Web 组件来为您隔离样式。
Shadow DOM 化模板
Web 组件可以通过 Shadow DOM 来隔离样式(并抽象化 HTML 实现)。这是同一个组件,使用 Shadow DOM 代替
查看 CodePen:具有本地样式的 Web 组件,作者 Chris Coyier (@chriscoyier) 在 CodePen 上。
请注意,功能仍然有效(尽管我们不得不通过 shadowRoot
进行 querySelector
),但我们完全失去了全局样式。Shadow DOM 边界(shadow root)阻止样式进出(有点像 iframe)。

据我所知,没有全局方法可以穿透该边界,因此如果您想引入样式,您必须将它们引入模板。
将样式(内联)移到 Web 组件内部
查看 CodePen:具有本地样式的 Web 组件,作者 Chris Coyier (@chriscoyier) 在 CodePen 上。
如果您既想真正使用 Shadow DOM,又想使用全局样式,那么这将非常令人讨厌。有趣的是,Shadow DOM 有一种用于打开和关闭的“模式”,用于允许或禁止 JavaScript 进出,但 CSS 却没有。
如果是您,您可能需要 @import
任何可以使用的全局样式表,以便引入这些全局样式,并希望它们被缓存,并且浏览器以不造成重大性能影响的方式智能处理它们。
链接到外部样式
我将使用 CodePen 的直接链接到 CSS 功能,将来自 Pen 本身的样式导入到 Web 组件中
查看 CodePen:具有本地样式的 Web 组件,作者 Chris Coyier (@chriscoyier) 在 CodePen 上。
显然,没有办法完全避免这种方式的非样式组件闪现现象,因此建议内联样式,直到出现这种情况。(嗯,查看 ::part
)。
自定义属性会穿过 Shadow DOM
另一个需要了解的重要事项是,CSS 自定义属性会穿透 Shadow DOM!没错,它们确实会。您可以在 CSS 中选择 Web 组件并在那里设置它们
查看 CodePen:具有自定义属性的 Web 组件,作者 Chris Coyier (@chriscoyier) 在 CodePen 上。
您通过 slot 指向的 HTML 可以全局样式化
所以如果你有像
<my-module>
<h2 slot="header">My Module</h2>
</my-module>
而您在定义 Shadow DOM 的地方使用该标题
<div class="module">
<slot name="header"></slot>
</div>
那么 <h2>
可以全局样式化,但 <div class="module">
则不能。
查看 CodePen:slots 和样式化 Web 组件,作者 Chris Coyier (@chriscoyier) 在 CodePen 上。
::part 和 ::theme
我没有过多地研究这个,因为我认为这仍然是一个正在开发中的规范,但最终可能会在这里发挥重要作用。Monica Dinculescu 在她的文章 ::part 和 ::theme,一个 ::explainer 中详细介绍了它。
看起来像是一种进入 Shadow DOM 的方法,但只针对与之匹配的精确级别,不会更深。
<h4><x-foo>
#shadow-root
<div part="some-box"><span>...</span></div>
<input part="some-input">
<div>...</div> /* not styleable
</x-foo></h4>
x-foo::part(some-box) { ... }
/* nope */
x-foo::part(some-box) span { ... }
自定义属性可以通过 Shadow DOM 边界访问,这很有趣。能够正确地对样式进行范围限定将非常有用,但遗憾的是,创建 Shadow DOM 边界依赖于客户端 JavaScript。
感谢这篇文章!我认为自定义属性可以穿透 Shadow DOM,而其他任何东西都不行,这非常令人困惑。
由于某种原因,我觉得在 vue.js 风格组件的时代,Web 组件在得到正确实现之前就已经过时了。有很多样板代码,而且,整个过程似乎有点古怪。或者也许我只是不明白它的好处。
相关内容:可构造样式表