首页 > 解决方案 > 将全局样式应用到 Shadow DOM 的正确方法

问题描述

这个问题与 StackOverflow 上的其他问题类似,但我找不到任何描述适用于我的情况和不推荐使用的方法的答案(我开始认为可能没有针对这种情况的任何好的解决方案)。

假设我们有一些 main.css 文件,其中包括按钮、列表、链接等的常用样式。所以它只是一些标准的 .css 文件,其中包含我们希望在应用程序中重用的常见样式。我们希望将相同的样式应用于带有 Shadow DOM 的 Web 组件。

据我所知,有几种方法可以实现这一目标:

  1. 使用不推荐使用的方法之一:::shadow、>>>、/deep/ 选择器。但是这些选择器现在已被弃用,所以我想这不是前进的好方法。
  2. 使用 css 变量。如果我们需要设置一些属性,这种方法非常适合自定义目的。但是如果我们想从 main.css 文件中迁移 10-20 种常用样式,那就太复杂了。
  3. 在 Shadow DOM 中使用 @import 语句或“链接”标签。它会起作用,但它会复制每个组件的所有样式。如果我们有 10 个 Web 组件,我们最终会得到 10 个完全相同样式的副本。这听起来也不是足够好的解决方案。特别是如果我们有很多常见的样式,从性能的角度来看,这听起来可能是一个糟糕的解决方案。
  4. 根本不要使用 Shadow DOM 并使用全局样式 :) 但这不是当前问题的解决方案。

我还检查了在 Angular 框架中如何解决相同的问题(我检查了 Angular 的第 5 版)。当我将封装行为设置为 Native 时,它​​实际上只是在复制样式(如上述 #3 中所述),我认为这不是最好的方式(但可能是目前最好的方式)。

那么,有没有人知道是否有任何其他方法可以解决这个问题而没有上述缺点?听起来 Shadow DOM 的当前缺点带来的问题比它试图解决的问题还要多。

标签: javascriptcssweb-componentshadow-dom

解决方案


解决方案 3 没有真正的缺点:

  1. 无论您将 CSS 样式应用于主文档中的 n 个元素,还是应用于 n Shadow DOM 中的 1 个元素,无论如何,该样式都将复制到整个 n 个元素。

  2. 如果你在 n Shadow DOM 中导入一个文档 n 次,实际上 il 只会被加载一次并通过浏览器缓存重用。

之后,il 将依赖于 Shadow DOM 和 CSS 样式的浏览器实现,您应该会看到只有数千个 Shadow DOM 的性能下降。


Chrome 73+ 和 Opera 60+ 的 2019 年更新

现在您可以直接实例化一个CSSStyleSheet对象并将其分配给不同的 Shadow DOM。

这样 HTML 就不会被复制。

var css = new CSSStyleSheet()
css.replaceSync( "@import url( main.css )" )
host.shadowRoot.adoptedStyleSheets = [css] 
host2.shadowRoot.adoptedStyleSheets = [css] 

您还可以将其应用于全局文档:

document.adpotedStyleSheets = [css]

另一个优点是样式表上的更新将应用于所有采用它的 Shadow DOM(和文档)。

 css.replaceSync( '.color { color: red }' )

推荐阅读