为啥将 * 选择器与 *::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 *::after
是pseudo-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-box
和border-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
不是继承属性,因此也必须在伪元素上明确提及。
注意:虽然伪元素被命名为before
和after
,但它们实际上是它所附加的元素的子元素。
举例说明继承:
看看下面的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` 元素一起使用? [复制]