为什么将 * 选择器与 *::before 和 *::after 结合使用

Why use * selector in combination with *::before and *::after

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

为了将框模型设置为 border-box,我将查看以下部分。

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

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

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

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

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

您可以获得有关框大小调整的更多信息here

To me, this seems obsolete because the * selector will already tag all elements.

没有。 * selector 只会 select 真正的 selector 在 DOM-Tree.

这是我给你做的一张图,使用前后伪元素可以这样插入元素:

伪元素在 DOM-Tree 之外。所以,使用 * 不会 select 他们:

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

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

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

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

引用自MDN

You can use only one pseudo-element in a selector. It must appear after the simple selectors in the statement.

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

A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.

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

是否*select所有元素?

没有*不覆盖伪元素。它们仅涵盖 DOM 中存在的真实元素。

From the W3C Spec:

The universal selector, written as a CSS qualified name [CSS3NAMESPACE] with an asterisk (* U+002A) as the local name, represents the qualified name of any element type. It represents any single element in the document tree in any namespace (including those without a namespace) if no default namespace has been specified for selectors.

重点是我的


为什么在 * select 下指定的 属性 或对某些人有效但对其他人无效?

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

另一方面,

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

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


说明继承的例子:

看看下面的代码片段,看看黑色 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

查看这两个 JSFiddle:

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

或试试这些片段:

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 之间更改框大小只会改变段落的大小,不会 它是 ::after 元素。正如其他人指出的那样,这是因为它们是如名称所示的 元素,必须单独定位。

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

* 目标 all elements.

::before::afterpseudo elements,所以不是 * 的目标,所以要将它们也作为目标,您可以使用您在 OP 中使用的代码。

你可以在不使用伪元素的情况下创建一个网站,它只是为那些使用它们的人准备的,所以他们有一个一致的盒子模型,当他们去使用一个 ::before::after 并且计算方式不同。

下面是来自CSS-Tricks

的伪元素结构

* 将仅定位元素。

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

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

的原因

它们不是 select 由 * 编辑的,因为它 select 只是元素。这就是为什么你不能 select 他们