[英]What is the ::content/::slotted pseudo-element and how does it work?
这对谷歌来说是不可能的,因为每篇谈论:before
和:after
伪元素的文章似乎都使用了“内容”这个词。
我在这篇CSS-Tricks 文章中听说过它,解释了如何实现图像滑块作为 Web 组件的示例用例。 它出现在里面的代码示例是这样的:
CSS
#slides ::content img {
width: 25%;
float: left;
}
HTML
<template>
...
<div class="inner">
<content select="img"></content>
</div>
</template>
它似乎指的是这个<content>
标记,它用于允许用户包含 Web 组件,但我很想更深入地理解这一点。
编辑:
进一步阅读后,在上述文章中,我发现了作者的“Shadow DOM CSS Cheatsheet”链接,其中包含一段解释::content
伪元素是什么的段落:
选择元素内部的分布式节点。 对于不支持原生选择器的浏览器,需要搭配 polyfill-next-selector。
::content h1 {
color: red;
}
来源:http ://robdodson.me/blog/2014/04/10/shadow-dom-css-cheat-sheet/
这很有帮助,但我仍然发现整个事件相当不透明。 任何额外的见解?
::content
伪元素在 Web 组件/Shadow DOM 的未来实现中被替换为::slotted
伪元素。 同样,此伪元素所针对的元素在最新版本的Shadow DOM 规范中已从<content
更改为<slot
> 。 您可以在此处查看有关该更改的相关讨论。
目前浏览器仍然支持<content>
和::content
。
概括:
::content
本质上是一种深入挖掘和设置ShadowHost
后代样式的方法,这些后代通常无法设置样式,因为您的 CSS 不知道在没有::content
的情况下查找 ShadowDOM 片段。
这个答案假设您至少对<template>
元素和Web Components有所熟悉,特别是ShadowDOM ,它处理ShadowTree
及其两个主要元素ShadowHost
和ShadowRoot
。
注意- 在撰写本文时,五种主要浏览器对 Web 组件的支持不到 50%(即使是带前缀的、默认关闭的支持)。 虽然所有现代浏览器都支持<template>
,但只有最新版本的 Chrome 和 Opera 完全支持 ShadowDOM; 在将about:config
( dom.webcomponents.enabled
) 中的必要功能切换为true后,Firefox 支持其中的部分功能。
使用ShadowDOM
的目标类似于 MVC 的关注点分离。 也就是说,我们希望将内容与表示分离,并允许在我们的代码中封装模板以帮助使其更易于管理。 我们已经在各种编程语言中实现了这一点,但在 HTML 和 CSS 中它仍然是一个问题一段时间。 此外,在 Web 应用程序中设置元素样式时,可能会与类名发生冲突。
通常,我们与LightDOM
(一种“Light Realm”)进行交互,但有时利用封装会有所帮助。 进入这种“Shadow Realm”(Web Components 的一部分)是一种通过允许封装来防止上述问题的新方法。 任何应用于ShadowTree
ShadowTree
的标记,即使使用完全相同的类或选择器也是如此。
当ShadowTree
(位于ShadowDOM
中)有来自LightDOM
的树分布在其中时,和/或当ShadowTree
被渲染时,浏览器会将结果转换为所谓的组合树。
当浏览器呈现您的代码时,内容将被分发并插入到新位置,而不是实际键入的位置。 这个分布式输出就是你看到的(和浏览器看到的),被称为composed tree
。 实际上,内容最初并不是按照现在出现的顺序输入的,但是您不会知道这一点,浏览器也不会。 如果愿意的话,“最终结果”和“原始代码”之间的这种分离是封装的主要好处之一。
Web Components & the Future of CSS是一个 40 分钟的关于 Web 组件的精彩视频,特别是关于 ShadowDOM,由ZachSaucier向我指出。
具体到您的问题, ::content
伪元素适用于所谓的分布式节点。 分布式节点是您放置在<content></content>
标记中的任何内容的另一个术语。 内容从其在原始标记中的位置分发到您在模板中放置<content>
标记的任何位置。
因此,当您需要 CSS 中的特定性时,通常可以处理选择器的一种方法是转到父元素并将其添加为选择器的一部分。 例如:如果.container {}
不够具体,您可以使用div .container {}
或.main .container {}
来使您的选择器工作。
考虑到 ShadowDOM 的意义,即作用域和封装,您必须意识到您创建的这个新 ShadowTree 是一个全新的(离散的)DOM 片段。 它与您的其他内容不在同一个“光域”中; 它在“影界”中。 那么,CSS 是如何知道以这个“影子领域”为目标的呢? 通过使用::content
伪元素!
::content
伪元素选择器充当分布式节点的父元素。HTML5Rocks在此处、 此处和此处有一系列教程,其中涵盖了更多信息并提供了一些很好的示例(请务必使用 Chrome 或 Opera 访问,直到更多浏览器支持这些功能)。
例如,查看 HTML5Rocks 中代码的修改和改进(由Leo编写)版本:
var div = document.querySelector('div'); var root = div.createShadowRoot(); var template = document.querySelector('template'); root.appendChild(template.content);
<template> <style> h3 { color: red; } content[select="h3"]::content > h3 { color: green; } ::content section p { text-decoration: underline; } </style> <h3>Shadow DOM</h3> <content select="h3"></content> <content select="section"></content> </template> <div> <h3>Light DOM</h3> <section> <div>I'm not underlined</div> <p>I'm underlined in Shadow DOM!</p> </section> </div>
也可在JSFiddle上使用(请记住在基于 WebKit 的浏览器中访问,例如 Chrome 或 Opera)
在这里您可以看到::content
section p
伪元素首先选择ShadowRoot
的内容,即标记中div
元素的内容,然后通过添加section p
进一步指定。
与正常的 CSS 选择器使用相比,这似乎是不必要的(例如,为什么不只使用section p {}
?),直到您回想一下,在遍历ShadowTree
时,您通常不能选择host
元素的后代(哪些分布式节点是) ,因为他们在我之前提到的“影界”之中。
太糟糕了! 不幸的是::content
是v0 ,并且已被弃用。
您现在应该使用v1 ::slotted
。
此外, <content>
已被弃用,取而代之的是<slot>
。
请参阅: https ://hayato.io/2016/shadowdomv1/
有一个很长的答案解释 :slotted on StackOverflow。
自 2020 年 5 月发布以来,已获得 38 票赞成
请参阅: ::slotted CSS 选择器用于 shadowDOM 插槽中的嵌套子项
我的建议是,删除这个 SO 问题,这样新的搜索就不会出现在 Web Components V0 答案的非常老的问题中
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.