为啥将 * 选择器与 *::before 和 *::after 结合使用 [重复]

Posted

技术标签:

【中文标题】为啥将 * 选择器与 *::before 和 *::after 结合使用 [重复]【英文标题】:Why use * selector in combination with *::before and *::after [duplicate]为什么将 * 选择器与 *::before 和 *::after 结合使用 [重复] 【发布时间】:2015-09-27 19:32:02 【问题描述】:

我正在查看 Twitter 引导框架,我确实有一个非常小的问题。

我将看到以下部分,以便将 box-model 设置为 border-box

*, *::after, *::before  box-sizing: border-box; 

但是,如果您查看 CSS 规范 * 以所有元素为目标,那么到底为什么要使用 *::after*::before 选择器?

对我来说,这似乎已经过时了,因为 * 选择器已经标记了所有元素。

【问题讨论】:

* 不针对伪元素 假设我有一个P元素,*::after会触发什么,因此p::after pseudo classes !== elements, all elements === *. 根据W3 recommendation,box-sizing 不是继承的,所以必须专门为伪元素设置。 @Mr_Green:伪类和伪元素都不是一回事。请参阅我对哈利回答的评论。 【参考方案1】:

你基本上回答了你自己的问题。 ::before::after伪元素。这个名字甚至暗示它们并不代表真正的元素。

选择器*, *::before, *::after 用于匹配:

* DOM 中存在的所有元素 *::before 伪元素 ::before 相对于 DOM 中存在的所有元素 *::after 伪元素 ::after 相对于 DOM 中存在的所有元素

由于伪元素不能作为完整元素(<html><head><body> 等)并且不是 DOM 的一部分,因此它们不匹配星号字符。它们仅在参考另一个元素选择时才匹配。出于同样的原因,它们不能在 javascript 中被选中。 JavaScript 只选择它可以在 DOM 中找到的元素,这对于伪元素来说是不正确的。

引用MDN:

您只能在选择器中使用一个伪元素。它必须出现在语句中的简单选择器之后。

W3C 使用以下定义定义了一个简单的选择器:

simple selector 是 type selector、universal selector、attribute selector、class selector、ID selector 或 pseudo-class。

简单的选择器旨在匹配 DOM 中存在的元素。伪元素必须遵循简单的选择器,因为它不是 DOM 本身的一部分,因此不能归类为元素。由于* 是一个简单的选择器,特别是universal selector,CSS 中的伪元素可以链接到它以匹配所有特定的伪元素类型。如果没有伪元素选择器,将只保留一个简单的选择器 (*)。

【讨论】:

问题是,为什么不直接写::before::after,就像写.some-class 而不是*.some-class 带有伪元素的东西让我抓狂。这些伪元素实际上是什么?如果我不使用 ::after 选择器会发生什么? @Pointy:从 OP 的评论来看,我认为这不是问题 ^ @Complexity ::before::after 选择器允许将某种“虚拟”元素注入另一个容器元素的开头或结尾。因此,span::before 可以让您将内容放在每个跨度的前面。请注意,这些是有意义的,因为 content CSS 属性。 @Cerbrus 是的,我同意 - 很抱歉造成混乱【参考方案2】:

原因是*::before and *::afterpseudo-elements。它们确实不是元素,这就是它们被称为pseudo 的原因。

* 没有选择它们,因为它只选择元素。这就是为什么你不能选择它们

【讨论】:

【参考方案3】:

::after 和 ::before 是 pseudo elements 并且它们相应地在元素之后或之前插入样式。

对于您的问题,*::after 和 *::before 用于管理出现的空格。如果你不这样做,box-sizing 就是 content-box,你会看到间距的差异(甚至我们肉眼看不到)。

您可以在here获取更多关于box-sizing的信息。

对我来说,这似乎已经过时了,因为 * 选择器已经标记了所有元素。

没有。 * 选择器只会选择DOM-Tree中的真正选择器。

这是我为您制作的一张图片,使用前后伪元素可以插入这样的元素:

伪元素位于 DOM 树之外。所以,使用* 不会选择它们:

【讨论】:

这不能回答我的问题。因此,我对每个元素都使用了* 选择器。那为什么我需要 after 选择器。不是*选择器定位后的元素吗? @Complexity .myClass::after 不以.myClass 之后的元素为目标,而是以您可以操作的伪元素为目标。顺便说一句伪手段:not genuine; pretended 被问到的问题是为什么*::before 选择器必须包含*。如果它是一个简单的类,例如,你不会写*.some-class,你会写.some-class @Pointy 被问到的问题是为什么* 不针对*::before。不是为什么*::before 包含* @dev-null 是的,很抱歉造成误解。 (不过我很好奇 :)【参考方案4】:

查看这两个 JSFiddles:

http://jsfiddle.net/86gc1w6f/ http://jsfiddle.net/gwbp2vpL/1/

或者试试这些sn-ps:

CSS:

* 
    box-sizing: content-box;


p 
    position: relative;
    width: 200px;
    border: 10px solid rgba(255, 0, 0, 0.5);


p::after 
    position: absolute;
    right: -100px;
    top: -10px;
    width: 100px;
    height: 30px;
    border: 10px solid rgba(0, 0, 255, 0.5);
    content: '';

HTML:

<p>
    A paragraph
</p>

content-boxborder-box 之间更改box-sizing 只会改变段落的大小,不是它是::after 元素。正如其他人所指出的,这是因为它们是顾名思义的元素,必须单独定位。

看起来 * 不针对伪元素(正如@Harry 指出的那样,按照the CSS specification)

【讨论】:

谢谢。这是我正在寻找的答案。再问一个问题,然后我会接受你的回答。当我没有使用content 的CSS 类时,我是否可以说我不需要定位*::after?我认为这是真的的原因是,否则页面上的所有内容都是* 选择器所针对的真实元素。 ::before::after 如果没有定义 content 属性,则不会呈现。你是这个意思吗?另外值得注意的是,您也可以使用不带 * 的 ::after 来定位所有 ::after 伪元素。正如其他人所指出的,旧版本的 IE 需要一个冒号(如早期 CSS2 规范中所定义) 确实如此。所以只有在直接通过css设置内容时才需要该选择器(所以它不是页面上的真实元素,在HTMl文件中没有标记)。【参考方案5】:

* 是否选择所有元素?

* 不包括伪元素。它们仅涵盖 DOM 中存在的真实元素。

来自W3C Spec

通用选择器,写成CSS qualified name [CSS3NAMESPACE],带有星号 (* U+002A) 作为本地名称,代表任何元素类型的限定名称。如果没有为选择器指定默认命名空间,则它表示任何命名空间(包括那些没有命名空间的)中的任何文档树中的单个元素

重点是我


为什么 * 选择器下指定的属性对某些人有效,而对其他人无效?

对于像color 这样的一些属性,您会产生* 应用于包括伪元素在内的所有元素的错觉,因为它们是子元素可以从其父元素继承的属性。

另一方面,box-sizing 不是继承属性,因此也必须在伪元素上明确提及。

注意:虽然伪元素被命名为beforeafter,但它们实际上是它所附加的元素的子元素。


举例说明继承:

看看下面的sn-p,看看黑色border是如何只应用于真实元素的。在伪元素中,只有p:after 得到border,因为它是直接在伪元素本身上指定的。 div:after 没有边框。

*  /* selects all real elements */
  border: 1px solid black; /* not an inheritable property and so pseudos don't get it */
  padding: 10px;
  color: red; /* inheritable property and so pseudos which are children inherit it */

div::after 
  content: 'abcd';
  margin: 4px;

p::after 
  content: 'abcd';
  margin: 4px;
  border: 1px solid red;
<div>abcd</div>
<p>abcd</p>

可继承的属性列表有哪些?

您可以找到有关子级可以从其父级here 继承的属性列表的更多详细信息。

【讨论】:

应该:: 用于伪元素,: 用于伪类。虽然 IE8 只支持伪元素虽然 : 通过扩展,所有简单的选择器只针对真实元素。伪元素是完全独立于元素及其简单选择器的类别。事实上,伪元素和伪类之间的许多区别之一是伪元素不是一个简单的选择器。由此可见,伪元素与简单的选择器有一套非常不同的语法规则,这就是为什么将两者混为一谈是一个严重的错误。【参考方案6】:

下面是来自CSS-Tricks的伪元素结构

* 将只针对元素。

*::after*::before 是伪元素,不是真实的,即它们不是 DOM 的一部分。它们位于内容和元素之间,因此您可以在不修改标记的情况下插入您希望的任何额外内容。

【讨论】:

谢谢。这么好的答案。但是,我不能接受多个答案,但我投了赞成票。 欢迎 :) 您可以很好地更改已接受的答案。开玩笑! ;) Tom 用代码更好地解释了它。 我也喜欢你的。这两篇文章的结合让我走上了正轨。【参考方案7】:

* 目标 all elements。

::before::after 是 pseudo elements,因此不是 * 的目标,因此您也可以使用您在 OP 中使用的代码来定位它们。

您可以在完全不使用伪元素的情况下创建一个网站,它只为使用它们的人提供,因此他们有一个一致的盒子模型,并且当他们使用 ::before 或时不会开始摸不着头脑::after 计算方式不同。

【讨论】:

以上是关于为啥将 * 选择器与 *::before 和 *::after 结合使用 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 :before 和 :after 伪元素需要 'content' 属性?

为啥 :before 和 :after 伪元素不能与 `img` 元素一起使用? [复制]

如何将选择器与 JavaScript 标识符正确组合?

将 MaterialUI 伪类选择器与 makeStyles 一起使用

将 JQuery 的日期选择器与引导程序一起使用

CSS3使用content属性来插入项目编号