Menu

CSS ::before 和 ::after 伪元素详解与示例

::before 和 ::after 直接用 CSS 在元素中插入生成内容,分别作为它的第一个和最后一个子元素。学习 content 属性、为什么必须写空的 content、如何定位它们、用 attr() 做提示框、计数器,以及它们在哪些地方不起作用。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

::before 和 ::after 的作用

::before 在元素中插入一个盒子,作为它的第一个子元素;::after 则作为最后一个子元素。盒子里放什么由 content 属性决定。HTML 中不会增加任何东西:浏览器根据 CSS 生成它们。

HTML 里只有 9 和 Tests pass。美元符号、“/ month”标签和对勾都来自 CSS。它们会继承元素的样式(字体、颜色),除非你像上面的例子那样覆盖它们。

语法

selector::before {
  content: "text";   /* required */
  /* any other styles */
}

selector::after {
  content: "";       /* empty string: a box with no text */
}
content 的值效果
"text"一个字符串。用 "\A" 表示换行(配合 white-space: pre),用 "\2192" 表示一个 Unicode 字符(→)
""一个空盒子,用来做图形和装饰
attr(data-label)元素某个属性的值
counter(step)一个 CSS 计数器的值
open-quote / close-quote适合元素语言的引号
none 或 normal不生成伪元素(normal 是默认值)

content 是必需的。没有它,无论你给 ::before 和 ::after 写多少其他属性,它们都不会被创建。

用 content: "" 做装饰图形

使用 content: "" 时,伪元素是一个空盒子,你可以设置它的大小和颜色。它默认是行内的,而行内盒子会忽略 width 和 height,所以要给它 display: block、inline-block 或 position: absolute:

定位伪元素

如果装饰要叠在元素上方或环绕在元素周围,就给伪元素设置 position: absolute,给元素本身设置 position: relative,这样偏移量就是相对于元素来计算的:

和伪类组合使用时要注意顺序:先写状态,再写伪元素,即 .link:hover::after,永远不要写成 .link::after:hover。

用 attr() 读取属性:提示框

attr() 把一个属性的值放进 content,这样一条规则就能在每个元素上显示不同的文字:

只在悬停时出现的提示框,键盘用户和触屏用户都看不到。重要的内容请直接放在页面上,或者在元素上加 tabindex="0",并在 :focus 时也显示它。

用计数器编号

CSS 计数器配合 ::before 可以自动编号,不用手动输入数字:

增加或删除一个步骤,编号会自动更新。

::before 和 ::after 不起作用的地方

伪元素被插入到元素内部,位于它的开始标签和结束标签之间。没有“内部”的元素无法显示它们:

  • <img>、<video>、<iframe>(替换元素)
  • <input>、<select>、<textarea>(表单控件),以及 <br>

有些浏览器会在复选框或损坏的图片上绘制它们,但表现并不一致。请把伪元素放在外层元素上:<span class="field"><input></span>,然后给 .field::after 设置样式。

常见错误

  • 没有 content。 这是什么都不显示的最常见原因。加上 content: ""。
  • 给行内伪元素设置尺寸。 在设置 display: block、inline-block 或 position: absolute 之前,width 和 height 不起作用。
  • 和状态组合时顺序写错。 a:hover::after 有效;a::after:hover 无效。
  • 使用绝对定位,但父元素没有定位。 这时伪元素会对齐到某个较远的祖先元素。给元素加上 position: relative。
  • 把真正的内容写在 CSS 里。 content 中的文字不能被选中或复制。信息要保留在 HTML 中。

常见问题

CSS 中的 ::before 有什么作用?

它创建一个伪元素,作为所选元素的第一个子元素,里面填充 content 属性指定的内容。::after 的作用相同,只是作为最后一个子元素。它们都不存在于 HTML 中,所以很适合用来做图标、标签和装饰。

为什么我的 ::before 或 ::after 不显示?

最常见的原因是缺少 content 属性:没有它,伪元素就不会生成。装饰用的空盒子请写 content: ""。其他原因还有:给行内伪元素设置了宽高(要给它 display: block 或 inline-block),或者用在了 <img>、<input> 这类无法容纳伪元素的元素上。

:before 和 ::before 有什么区别?

行为上没有区别。两个冒号的 ::before 是当前的语法,用来标明伪元素;一个冒号的 :before 是较老的 CSS2 写法,浏览器对 before、after、first-line 和 first-letter 仍然接受这种写法。

可以在 img 或 input 上使用 ::before 吗?

不可靠。伪元素被插入到元素的内容内部,而 <img> 这样的替换元素和 <input> 这样的表单控件没有可以容纳它们的内容盒子。请把元素包在 <span> 或 <div> 中,把伪元素加在外层元素上。

屏幕阅读器能读出 CSS ::before 的内容吗?

一般可以:content 中的文字通常会被计入无障碍名称,但它不能被选中或复制。真正的信息要放在 HTML 中,伪元素只用于装饰和小的视觉提示。

Coddy 编程语言插图

和 Coddy 一起学编程

开始