搜索

首页  >  问答  >  正文

为什么:before和:after伪元素需要一个'content'属性?

在以下情况下,为什么:after选择器需要一个content属性才能起作用?


.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>


注意,在没有指定content属性之前,你看不到伪元素。


.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>


为什么这是预期的功能?你可能会认为display:block会强制元素显示出来。奇怪的是,你实际上可以在Web调试工具中看到样式,但它们不会显示在页面上。

P粉653045807P粉653045807500 天前536

全部回复(2)我来回复

  • P粉285587590

    P粉2855875902023-07-18 14:30:26

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

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

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

    ::before, ::after {
        content:'';
    } 

    回复
    0
  • P粉225961749

    P粉2259617492023-07-18 10:20:40

    为每个::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的原因。)

    回复
    0
  • 取消回复