::first-line对行内元素无效,因为它只作用于块级容器中渲染后的第一行文本,而span等行内元素不生成行框(line box),无法提供首行上下文。

为什么::first-line对行内元素无效
因为::first-line只作用于块级容器(如p、div、h1)中**第一行的文本内容**,它不选择元素本身,而是选择“渲染后第一行的字符范围”。如果父容器是span、a这类默认display: inline的元素,即使里面文字换行,它也没有“第一行”的上下文概念——浏览器根本不为纯行内元素生成行框(line box)来供伪元素钩取。
常见错误现象:span::first-line { color: red; } 完全不生效,控制台也无报错,容易误以为是写法错了。
- 必须确保目标元素是块级或至少设为
display: block/display: table等能触发行盒生成的显示类型 - 若原意是给某段落首字变色,直接用
p::first-line,别套在span上再试图控制 -
::first-line不能嵌套,也不能选中子元素——它只作用于文本节点的视觉首行
::first-line支持哪些CSS属性
它只接受一部分“文本相关”的CSS属性,超出范围的声明会被静默忽略(不报错,但不生效)。这是最容易被忽略的兼容性陷阱。
可用属性包括:color、font系列(font-size、font-weight等)、text-decoration、text-transform、letter-spacing、word-spacing、line-height(注意:仅影响该行,不影响整体段落行高)。
立即学习“前端免费学习笔记(深入)”;
-
margin、padding、border、background—— 全部无效 -
display不能设为flex或grid,设了也当没写 - 在Firefox中,
text-shadow支持;Chrome/Safari早期版本曾不支持,现在基本 OK,但别依赖它做关键视觉
为什么中文段落首行样式经常“断掉”
不是bug,是预期行为:::first-line选取的是“排版后第一行”,而中文换行逻辑受white-space、word-break、overflow-wrap和容器宽度共同影响。一旦窗口缩放、字体加载延迟或内容动态插入,首行实际包含的字数可能变化,导致样式“跳变”或应用到错误位置。
典型场景:响应式页面里一个p宽从600px缩到300px,原来首行5个字,现在变成3个字,::first-line自动重算并只作用于新首行的3个字。
- 不要指望它稳定控制“前N个字”,它控制的是“视觉首行”,不是“语义前缀”
- 避免和
text-indent混用——缩进本身属于首行,但text-indent值不会改变::first-line的选取范围 - 若需精确控制首字(比如古籍排版),用
<span class="first-char">第</span>手动标记,比依赖伪元素可靠
IE和旧版Edge对::first-line的特殊限制
IE8+ 支持::first-line,但只认单冒号语法:first-line;双冒号::first-line在IE中完全无效。而现代浏览器已普遍要求双冒号以区分伪类与伪元素,所以写法必须兼顾。
更隐蔽的问题是:IE/旧Edge中,如果父元素设置了font-size: 0(常用于清除inline-block间隙),::first-line会直接失效——哪怕后续子元素又把字号调回来。
- 兼容写法:同时写
p:first-line和p::first-line,让老IE走前者,新浏览器走后者 - 避免在
::first-line父容器上设font-size: 0,改用letter-spacing: -0.31em之类替代方案 - 移动端WebView(尤其Android 4.x)存在类似IE的解析缺陷,建议用Can I Use查具体UA下的支持表,别只看“CSS Pseudo-Elements”大类










