Shadow DOM 元素可以继承 CSS 吗?

Posted

技术标签:

【中文标题】Shadow DOM 元素可以继承 CSS 吗?【英文标题】:Can Shadow DOM elements inherit CSS? 【发布时间】:2014-10-02 09:11:14 【问题描述】:

我正在听这一集 javascript Jabber:

http://javascriptjabber.com/120-jsj-google-polymer-with-rob-dodson-and-eric-bidelman/

Rob 曾说过:

每个人都有第一个倾向,因为它很有意义。你会说,“Bootstrap 是组件。我只是要把它们做成标签。”但是随后您会遇到这样一个事实,即 Bootstrap 样式表只是一个大而长的样式表,它是在假设它可以触及文档的每个部分的情况下编写的。当你突然对标记的部分进行范围界定时,对它进行范围界定以使 CSS 无法到达它,CSS 实际上必须与它一起在 Shadow DOM 中,你必须从头开始编写该元素,那就是我认为人们一开始会感到非常困惑和沮丧。

这让我想知道,您将如何使用 Web 组件解决这个问题? Shadow DOM 模板有没有办法继承通用样式,或者您是否必须为每个单独的组件重复共享 CSS?还是别的什么?

【问题讨论】:

这个问题不是“太宽泛” - 它有一个非常简洁的答案(无论如何在真正的 Shadow DOM 实现中)。 我已经发布了不同的方法来解决问题,请参阅最后一个答案。 Shadow DOM 创建新的 dom 树。所以它提供了封装。您可以访问 :host 和/或 :host-context() 和 ::shadow ,这样您就可以有一个可以访问影子 DOM 元素的全局主题的概念,就像您可以在 今天。此外,Web 组件规范的其他部分(如模板和 html 导入)将提供更简洁、更可共享的组件。 【参考方案1】:

这是它工作的一个例子:http://jsbin.com/zayih/1/edit?html,css,output

虽然使用#placeholder定位它时它似乎不起作用

在 Chrome devtools 配置选项卡中打开“显示用户代理影子 DOM”,然后检查 <input> 以了解我的意思

【讨论】:

【参考方案2】:

注意:以下答案的内容不再相关,因为讨论的功能已被弃用一段时间。不要使用示例代码,但可以随意浏览一下过去的互联网。


在完整的 Shadow DOM 实现中,CSS 有一个 ::shadow 伪类,还有一个 /deep/ 组合子。

::shadow 伪类可以让你闯入一个元素下的影子 DOM,它匹配影子根。 /deep/ 组合器有效地完全打开了影子 DOM。

因此,如果你有一个 <x-foo> 元素和 <span> 元素,你可以用

x-foo::shadow span  color: red; 

或者将任何阴影 DOM 中的所有 <spans> 设为红色:

body /deep/ span  color: red; 

【讨论】:

我知道 ::shadow 和 /deep/,但似乎远非一个优雅的解决方案。有什么更好的吗? @anders ??什么会更好?它比其他 CSS 优雅吗? /deep/::shadow>>> 已弃用,最终将被删除。 @GünterZöchbauer 这很有趣;范围模块的31 Jan 2016 draft 仍然包括::shadow>>>,尽管它们标有“问题”。 有趣。 Chrome 问题中的讨论不是关于是否删除,而是在删除之前将其保留多长时间。 Polymer 团队也不再在任何地方使用它们。我想这已经解决了。【参考方案3】:

看看这个鲜为人知的方法:

The <core-style> Polymer element

您可以在 html 导入文件中定义样式:

<core-style id="x-test">
  :host 
    backgound-color: steelblue;
  
</core-style>

然后你可以在多个元素中使用它们:

<polymer-element name="x-test" noscript>
  <template>
    <core-style ref="x-test"></core-style>
    <content></content>
  </template>
</polymer-element>

在this well written article,您可以阅读有关如何使用该技术的更多信息。

但是,我能想到的一个缺点是无法通过这种技术使用 SASS,因为样式是在 &lt;core-style&gt; 标记内而不是在 &lt;style&gt; 元素内定义的,并且没有明确的方法来导入外部样式表。

【讨论】:

【参考方案4】:

我想我明白你在问什么。您可以在每个自定义元素中使用链接来包含您的主要样式或扩展包含它的现有元素。例如(使用聚合物):

<polymer-element name="ui-button" noscript>
  <template>
    <link rel="stylesheet" href="main.css"/>
    <div class="class-from-main" style="">
      <content></content>
    </div>
  </template>
</polymer-element>

我觉得值得你读一读:https://github.com/necolas/normalize.css/issues/408

【讨论】:

【参考方案5】:

无论过去需要什么 hack,shadow dom / CSS 的当前状态是您可以链接到外部样式表。 MDN 上的更多信息:https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM#Internal_versus_external_styles

然后,您可以拥有所有组件都引用的某种实用样式表(Tailwind 或类似的),这样您就不会重复 CSS。理论上,该 CSS 文件会被下载一次,缓存起来,然后每个自定义元素都可以使用其中的类(只要它们都链接到它)。

【讨论】:

以上是关于Shadow DOM 元素可以继承 CSS 吗?的主要内容,如果未能解决你的问题,请参考以下文章

我可以在 Shadow DOM 中获得一个按钮来提交不在 Shadow DOM 中的表单吗?

有人知道如何使用 selenium webdriver 识别 shadow dom web 元素吗?

有办法去掉从父级元素继承下来的 CSS 样式吗

基于 Shadow DOM 根的字体大小 css-values

CSS的三大特性

Shadow dom 中的 FontAwesome svg