简体   繁体   English

什么是 ::content/::slotted 伪元素,它是如何工作的?

[英]What is the ::content/::slotted pseudo-element and how does it work?

This is impossible to Google for because every article talking about the :before and :after pseudo-elements seems to use the word 'content'.这对谷歌来说是不可能的,因为每篇谈论:before:after伪元素的文章似乎都使用了“内容”这个词。

I heard about it in this CSS-Tricks article, explaining how to implement an image slider as an example use-case for web components.我在这篇CSS-Tricks 文章中听说过它,解释了如何实现图像滑块作为 Web 组件的示例用例。 The code example it appears inside is thus:它出现在里面的代码示例是这样的:

CSS CSS

#slides ::content img {
   width: 25%;
   float: left;
}

HTML HTML

<template>
  ...
  <div class="inner">
    <content select="img"></content>
  </div>
</template>

It seems to be referring to this <content> tag, which is used to allow the user to include Web Components, but I would love to understand this more deeply.它似乎指的是这个<content>标记,它用于允许用户包含 Web 组件,但我很想更深入地理解这一点。

EDIT:编辑:

After reading further, in the aforementioned article, I discovered a link the author's "Shadow DOM CSS Cheatsheet" which includes a passage that explains what the ::content pseudo-element is:进一步阅读后,在上述文章中,我发现了作者的“Shadow DOM CSS Cheatsheet”链接,其中包含一段解释::content伪元素是什么的段落:

Selects distributed nodes inside of an element.选择元素内部的分布式节点。 Needs to be paired with polyfill-next-selector for browsers that do not support the native selector.对于不支持原生选择器的浏览器,需要搭配 polyfill-next-selector。

::content h1 {
    color: red;
}

Source:http://robdodson.me/blog/2014/04/10/shadow-dom-css-cheat-sheet/来源:http ://robdodson.me/blog/2014/04/10/shadow-dom-css-cheat-sheet/

This is helpful, but I still find the whole affair rather opaque.这很有帮助,但我仍然发现整个事件相当不透明。 Any additional insights?任何额外的见解?

The ::content pseudo-element is being replaced in future implementations of Web Components / Shadow DOM with the ::slotted pseudo-element. ::content伪元素在 Web 组件/Shadow DOM 的未来实现中被替换为::slotted伪元素。 Likewise, the element targeted by this pseudo-element has changed from <content to <slot > in the latest version of the Shadow DOM specification .同样,此伪元素所针对的元素在最新版本的Shadow DOM 规范中已从<content更改为<slot > 。 You can see related discussion about that change here .您可以在此处查看有关该更改的相关讨论。

Currently browsers still support <content> and ::content .目前浏览器仍然支持<content>::content


Original answer:原答案:


Summary:概括:

::content is essentially a way to dig deeper and style descendants of the ShadowHost , which normally aren't available to be styled, because your CSS doesn't know to look for the ShadowDOM fragment without ::content . ::content本质上是一种深入挖掘和设置ShadowHost后代样式的方法,这些后代通常无法设置样式,因为您的 CSS 不知道在没有::content的情况下查找 ShadowDOM 片段。


This answer assumes you are at least somewhat familiar with the <template> element and Web Components , specifically the ShadowDOM , which deals with ShadowTree s and their two main elements, ShadowHost and ShadowRoot .这个答案假设您至少对<template>元素和Web Components有所熟悉,特别是ShadowDOM ,它处理ShadowTree及其两个主要元素ShadowHostShadowRoot

Note - As of this writing, there is less than 50% support (even prefixed, off-by-default support) for Web Components across the five major browsers.注意- 在撰写本文时,五种主要浏览器对 Web 组件的支持不到 50%(即使是带前缀的、默认关闭的支持)。 While all modern browsers support <template> , only recent versions of Chrome and Opera support the ShadowDOM fully;虽然所有现代浏览器都支持<template> ,但只有最新版本的 Chrome 和 Opera 完全支持 ShadowDOM; with Firefox supporting parts of it after you toggle the requisite feature in about:config ( dom.webcomponents.enabled ) to true .在将about:config ( dom.webcomponents.enabled ) 中的必要功能切换为true后,Firefox 支持其中的部分功能。

The goal of using the ShadowDOM is similar to MVC's separation of concerns .使用ShadowDOM的目标类似于 MVC 的关注点分离 That is, we want to separate our content from our presentation and allow for encapsulated templates in our code to help make it more manageable.也就是说,我们希望将内容与表示分离,并允许在我们的代码中封装模板以帮助使其更易于管理。 We have this already in various programming languages, but it's remained a problem for some time in HTML and CSS.我们已经在各种编程语言中实现了这一点,但在 HTML 和 CSS 中它仍然是一个问题一段时间。 Further, there can be conflicts with class names when styling elements in web apps.此外,在 Web 应用程序中设置元素样式时,可能会与类名发生冲突。

Normally, we interact with the LightDOM (a sort of "Light Realm"), but sometimes it would be helpful to take advantage of encapsulation.通常,我们与LightDOM (一种“Light Realm”)进行交互,但有时利用封装会有所帮助。 Crossing into this sort of "Shadow Realm" (part of Web Components) is a new method to prevent the problems mentioned above by allowing encapsulation .进入这种“Shadow Realm”(Web Components 的一部分)是一种通过允许封装来防止上述问题的新方法。 Any styles applied to markup in your ShadowTree won't apply to markup outside of your ShadowTree , even if the exact same classes or selectors are used.任何应用于ShadowTree ShadowTree的标记,即使使用完全相同的类或选择器也是如此。

When the ShadowTree (which lives in the ShadowDOM ) has a tree from the LightDOM distributed within it, and/or when the ShadowTree is rendered, the result is converted by the browser into what is called a composed tree .ShadowTree (位于ShadowDOM中)有来自LightDOM的树分布在其中时,和/或当ShadowTree被渲染时,浏览器会将结果转换为所谓的组合树

When the browser renders your code, content is being distributed and inserted at new locations other than where it was physically typed.当浏览器呈现您的代码时,内容将被分发并插入到新位置,而不是实际键入的位置。 This distributed output is what you see (and what the browser sees), and is called the composed tree .这个分布式输出就是你看到的(和浏览器看到的),被称为composed tree In reality, the content is not originally typed in the order that it now appears, but you won't know this, and neither will the browser.实际上,内容最初并不是按照现在出现的顺序输入的,但是您不会知道这一点,浏览器也不会。 This separation between "end result" and "original code", if you will, is one of the main benefits of encapsulation.如果愿意的话,“最终结果”和“原始代码”之间的这种分离是封装的主要好处之一。

Web Components & the Future of CSS is a great 40-minute video on Web Components and specifically the ShadowDOM, pointed out to me by ZachSaucier . Web Components & the Future of CSS是一个 40 分钟的关于 Web 组件的精彩视频,特别是关于 ShadowDOM,由ZachSaucier向我指出。


Specific to your question, the ::content pseudo element applies to what are called distributed nodes .具体到您的问题, ::content伪元素适用于所谓的分布式节点 A distributed node is another term for whatever you put within the <content></content> tags.分布式节点是您放置在<content></content>标记中的任何内容的另一个术语。 The content is distributed from its place in the original markup to wherever you have placed your <content> tags in the template.内容从其在原始标记中的位置分发到您在模板中放置<content>标记的任何位置。

So, when you need specificity in CSS, one way you can handle selectors normally is that you go to the parent element and add that in as part of the selector.因此,当您需要 CSS 中的特定性时,通常可以处理选择器的一种方法是转到父元素并将其添加为选择器的一部分。 Ex: if .container {} is not specific enough, you might use div .container {} or .main .container {} in order to make your selector work.例如:如果.container {}不够具体,您可以使用div .container {}.main .container {}来使您的选择器工作。

Thinking about the point of the ShadowDOM, which is scoping and encapsulation, you have to realize that this new ShadowTree you've created is a completely new (discrete) DOM fragment.考虑到 ShadowDOM 的意义,即作用域和封装,您必须意识到您创建的这个新 ShadowTree 是一个全新的(离散的)DOM 片段。 It's not in the same "Light Realm" as the rest of your content;它与您的其他内容不在同一个“光域”中; it's in a "Shadow Realm".它在“影界”中。 So, how does the CSS know to target this "Shadow Realm"?那么,CSS 是如何知道以这个“影子领域”为目标的呢? By using the ::content pseudo-element!通过使用::content伪元素!

The ::content pseudo-element selector acts as the parent element of distributed nodes. ::content伪元素选择器充当分布式节点的父元素。

HTML5Rocks has a great sequence of tutorialshere , here , and here which cover more information and give some great examples (be sure to visit with Chrome or Opera until more browsers support these features). HTML5Rocks在此处此处此处有一系列教程,其中涵盖了更多信息并提供了一些很好的示例(请务必使用 Chrome 或 Opera 访问,直到更多浏览器支持这些功能)。

For example, see this modified and improved (by Leo ) version of the code from HTML5Rocks:例如,查看 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>

Also available on JSFiddle (Remember to visit in a WebKit-based browser like Chrome or Opera)也可在JSFiddle上使用(请记住在基于 WebKit 的浏览器中访问,例如 Chrome 或 Opera)

Here you can see that the ::content section p pseudo element is first selecting the content of the ShadowRoot , which is the contents of the div element in your markup, and then specifying further by adding section p .在这里您可以看到::content section p伪元素首先选择ShadowRoot的内容,即标记中div元素的内容,然后通过添加section p进一步指定。

This may seem unnecessary when compared to normal CSS selector usage (for example, why not just use section p {} ?), until you recall that, when traversing a ShadowTree , you cannot normally select descendants of host elements (which distributed nodes are), because they are in the "Shadow Realm" I mentioned earlier.与正常的 CSS 选择器使用相比,这似乎是不必要的(例如,为什么不只使用section p {} ?),直到您回想一下,在遍历ShadowTree时,您通常不能选择host元素的后代(哪些分布式节点是) ,因为他们在我之前提到的“影界”之中。

Too bad!太糟糕了! Unfortunately ::content is v0 , and was deprecated.不幸的是::contentv0 ,并且已被弃用。

You should now use the v1 ::slotted .您现在应该使用v1 ::slotted

Also, <content> was deprecated in favor of <slot> .此外, <content>已被弃用,取而代之的是<slot>

Please see: https://hayato.io/2016/shadowdomv1/请参阅: https ://hayato.io/2016/shadowdomv1/

Also see: Web Components - why <content> was replaced with <slot>另请参阅: Web 组件 - 为什么将 <content> 替换为 <slot>

There is a VERY long answer explaining :slotted on StackOverflow.有一个很长的答案解释 :slotted on StackOverflow。

Which got 38 upvotes since it was posted in May 2020自 2020 年 5 月发布以来,已获得 38 票赞成

See: ::slotted CSS selector for nested children in shadowDOM slot请参阅: ::slotted CSS 选择器用于 shadowDOM 插槽中的嵌套子项

My advice, delete this SO question so new searches don't end up in VERY old questions with Web Components V0 answers我的建议是,删除这个 SO 问题,这样新的搜索就不会出现在 Web Components V0 答案的非常老的问题中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM