该用 ::first-line 而不是 ::first-letter 时,是需强调整行语义起始(如新闻导语、诗歌首行),它匹配渲染后视觉第一行全部文本,受响应式布局影响;::first-letter 仅作用于跳过前置空白和标点后的首个可渲染字形,适用首字下沉等场景。

什么时候该用 ::first-line 而不是 ::first-letter
当你要强调整行语义起始(比如新闻导语、诗歌首行、引文开头),而不是单个字形时,选 ::first-line。它匹配的是渲染后视觉第一行的全部文本,受 width、font-size、换行策略实时影响——窗口缩放时样式会自动重算,适合响应式排版。
常见误用是把它当成“源码第一行”,但实际效果可能跨单词甚至跨标点:如果段落开头有 <em>Important</em> note...,且 <em></em> 内容刚好撑满第一行,那整个 <em></em> 文本都会被 ::first-line 影响;但若其中插入了 display: block 元素(如 <img> 或 <div>),该元素本身不会被选中,其后文本仍可能属于第一行。
<p>支持的属性有限:<code>font-weight、color、text-transform、letter-spacing 可用;float、width、position 无效。
::first-letter 实际生效的字符范围比你想象的窄
它不简单取 DOM 中第一个字符,而是跳过所有前置空白、换行符、制表符,再跳过开头连续标点(如 "、「、—、$),最终选中第一个“可渲染字形”。中文取首汉字,英文取首字母——但像 U.S.A. 这类缩写,通常只命中 U,后面的点号不算。
必须满足两个前提才生效:
- 父元素是块级容器(
<p></p>、<div>、<code><blockquote></blockquote>),<span></span>或<input>上直接写无效 - 父元素不能是
display: inline(除非显式设为inline-block或block) -
::first-letter选中的字符,也会被::first-line包含——所以如果两者都设了color,::first-letter的声明优先级更高(同权重下后写的覆盖先写的) - 不要试图用
::first-line span这类组合选择器,CSS 规范明确禁止嵌套伪元素选择器,浏览器会直接忽略整条规则 - 如果段落开头有
::before生成内容,它会被计入第一行;但若该生成内容设了display: block,Firefox 会直接丢弃整个::first-line规则 - 旧版 Safari(≤14)对中文标点开头的段落,
::first-letter可能完全不触发——建议在首字符前加零宽空格或确保首字符是汉字/字母 -
::first-line在 flex 容器子项中行为不一致:Chrome 认为它是块级上下文,Firefox 可能拒绝应用——统一用display: block包裹目标元素更稳妥 - 伪元素不继承父级
font-feature-settings,如果首字母需要 OpenType 特性(如小型大写字母),必须在::first-letter规则里单独声明
支持的样式更受限:float 可用(常用来实现首字下沉),但 vertical-align 仅在 float: none 时有效;margin、padding、border 可用,width、height 不行。
同时使用 ::first-letter 和 ::first-line 的坑
它们可以共存于同一段落,但要注意层叠顺序和属性冲突:
典型成功场景是杂志式排版:首字母放大 + 浮动下沉,首行其余文字加粗 + 字距微调,中间用 margin-right 留出呼吸感。
现代浏览器里真正要警惕的兼容性问题
主流浏览器(Chrome 120+、Firefox 115+、Safari 17+)对这两个伪元素的支持已很稳定,但仍有三个细节容易翻车:
最常被忽略的一点:这两个伪元素都**无法通过 JavaScript 查询计算样式**(getComputedStyle(el).getPropertyValue('color') 对 ::first-letter 返回空字符串),调试只能靠 DevTools 的伪元素面板手动检查。











