::first-line 仅对块级容器中由真实文本构成的首行生效,不支持 inline、flex 等容器;仅接受 color、font-、text-、line-height、background 等行内相关属性,禁用 margin/padding/border 等布局属性;其首行范围随响应式变化动态重算,且与 ::first-letter 共存时存在嵌套覆盖关系。

为什么 ::first-line 有时完全不生效
根本原因通常是父元素的 display 类型或文本结构不满足伪元素触发条件。它只对「块级容器中的首行可渲染文本」起作用,且该行必须由真实文本内容构成——如果首行被 <br>、空格占位符或 display: inline-block 子元素提前截断,::first-line 就会静默失效。
实操建议:
- 确保父元素是
display: block或display: table-cell(inline和flex容器不支持) - 避免在段落开头用
<span style="display: inline-block">包裹文字,它会让首行“不可见”于伪元素计算逻辑 - 检查是否被更具体的 CSS 规则覆盖,比如
p { font-size: 14px; }比p::first-line { font-size: 16px; }优先级低,但若后者没生效,大概率是选择器未命中而非样式被覆盖
::first-line 支持哪些 CSS 属性
它不是全量样式接管者,仅接受与「行内格式」直接相关的属性。浏览器会忽略其他声明,且不同引擎处理略有差异(如 Safari 对 background 的支持比 Firefox 更宽松)。
能安全使用的属性包括:
立即学习“前端免费学习笔记(深入)”;
-
color、font-*系列(font-size、font-weight、font-style等) -
text-decoration、text-transform、letter-spacing、word-spacing -
line-height(注意:它影响的是整行盒的高度,不是字体大小) -
background(仅当整行无换行、无浮动干扰时稳定生效)
明确不支持:margin、padding、border、width、height、transform、display —— 写了也白写。
响应式场景下 ::first-line 的行为陷阱
首行范围不是静态的:它随视口宽度、字体大小、字间距变化实时重算。这意味着同一段文字在桌面端首行可能是前 80 字符,在手机上可能只剩前 20 字符——而你的 ::first-line 样式会无差别套用到这“新首行”上。
常见问题与对策:
- 小屏下首行只剩一个词(如“Lorem”),加粗后显得突兀 → 改用媒体查询限制最小字号:
@media (max-width: 480px) { p::first-line { font-size: inherit; } } - 中英文混排时因字体度量差异导致首行断点偏移 → 避免依赖绝对字符数,改用语义化标记(如给首句加
<span class="lead">)更可控 - 使用
font-size: clamp()时,::first-line的字号缩放可能滞后于布局重排 → 测试真机,必要时用forced-colors媒体查询兜底
和 ::first-letter 套用时的顺序与冲突
两者可共存,但渲染顺序固定:::first-letter 在 ::first-line 内部嵌套生效。也就是说,::first-line 设置的 color 会被 ::first-letter 的同名属性覆盖,但 ::first-letter 无法修改 ::first-line 设定的 line-height。
关键细节:
- 若
::first-letter设了float: left,它会脱离行流,此时::first-line的background可能无法填满整行(留出浮动区域空白) - 不要对同一元素同时用
::first-line和text-indent:后者会移动整行位置,但伪元素样式仍按原始布局计算,造成视觉错位 - Chrome 115+ 开始支持
::first-line内嵌em单位相对计算,但 Safari 目前仍以父元素font-size为基准,跨浏览器需谨慎
真正麻烦的从来不是怎么写,而是你改完 ::first-line 后发现某台安卓机上首行突然多包了一行字——那八成是系统 WebView 对换行符(\u2028)的解析和桌面 Chrome 不一致。这种细节,不真机连测三次根本绕不过去。


















