Why do the :before and :after pseudo-elements need a 'content' attribute?
P粉653045807
P粉653045807 2023-07-17 18:43:31
0
2
534

In the following situation, why does the :after selector need a content attribute to work?


.test {
    width: 20px;
    height: 20px;
    background: blue;
    position:relative;
}
			
.test:after {
    width: 20px;
    height: 20px;
    background: red;
    display: block;
    position: absolute;
    top: 0px;
    left: 20px;
}
<div class="test"></div>


Note that you cannot see pseudo elements before specifying the content attribute.


.test {
    width: 20px;
    height: 20px;
    background: blue;
    position:relative;
}
			
.test:after {
    width: 20px;
    height: 20px;
    background: red;
    display: block;
    position: absolute;
    top: 0px;
    left: 20px;
    content:"hi";
}
<div class="test"></div>


Why is this an expected feature? You might think that display:block would force the element to be displayed. The weird thing is that you can actually see the styles in the web debugging tool, but they don't show up on the page.

P粉653045807
P粉653045807

reply all(2)
P粉285587590

以下是对各种W3C规范和草案的参考:

选择器 Level 3
:before 和 :after 伪元素
content 属性
应用于 ::before 和 ::after 伪元素的样式会影响生成内容的显示。content 属性就是这个生成的内容,如果没有它,就会默认假设 content: none,意味着没有内容可以应用样式。

如果你不想重复多次使用 content:'',你可以通过在CSS中全局地为所有 ::before 和 ::after 伪元素设置样式来覆盖这一点(JSFiddle 示例):

::before, ::after {
    content:'';
} 
P粉225961749

为每个::before和/或::after伪元素声明content: ''的原因是因为content的初始值是normal,这在::before和::after伪元素上计算为none。请参考规范。

content的初始值不是空字符串而是计算为none的值,原因有两个:

  1. 在每个元素的开头和结尾都有空的内联内容是相当愚蠢的。请记住,::before和::after伪元素的最初目的是在源元素的主要内容之前和之后插入生成的内容。当没有内容可插入时,创建一个额外的盒子来插入空内容是没有意义的。因此,none值告诉浏览器不要费心创建额外的盒子。

    使用空的::before和::after伪元素来创建仅用于布局美观的额外盒子的做法是相对较新的,一些纯粹主义者甚至可能认为这是一种hack。

  2. 在每个元素的开头和结尾都有空的内联内容意味着每个(非替换)元素 - 包括html和body - 默认情况下将生成不止一个盒子,而是最多三个盒子(对于已经生成多个主要盒子的元素,例如具有列表样式的元素,可能会生成更多盒子)。你实际上会使用多少个额外的盒子?这可能会使布局的成本增加两倍,但获得的收益非常少。

    实际上,即使在本十年,页面上不到10%的元素会需要用于布局的::before和::after伪元素。

因此,这些伪元素是选择性的 - 因为选择性退出它们不仅浪费系统资源,而且在考虑到它们的原始目的时纯粹是不合逻辑的。出于性能原因,我也不建议使用::before、::after为每个元素生成伪元素。

但你可能会问:为什么不将display属性在::before、::after上默认为none呢?简单来说:因为display的初始值不是none,而是inline。将inline计算为none在::before、::after上不是一个选项,因为这样你将永远无法以内联方式显示它们。将display的初始值设为none在::before、::after上也不是一个选项,因为一个属性只能有一个初始值。(这就是为什么content的初始值始终是normal,并且在::before、::after上被定义为计算为none的原因。)

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template