text-indent: 2em是首选,因其在多数中文字体下视觉接近两汉字宽,具备响应式、无障碍友好、全浏览器兼容(ie9+)等优势;2ch受字体影响缩进不足且ie不支持,32px则无法随字号缩放。

用 text-indent: 2em 是最实用、兼容性最好、语义最清晰的方案,不是“差不多”,而是现代中文网页排版的事实标准。
为什么 text-indent: 2em 是首选,而不是 2ch 或 32px
多数中文字体(如 “PingFang SC”、“Microsoft YaHei”、“Noto Sans CJK”)在常规字号下,1em 非常接近一个汉字的视觉宽度——这不是巧合,是字体设计与 CSS 单位长期协同演化的结果。所以 2em 在桌面 Chrome/Firefox/Safari 和 Android WebView 中表现高度一致。
2ch 看似更“字符化”,但问题在于:中文字体大多非等宽,“0”的字宽 ≠ 汉字字宽;实测中,思源黑体下 2ch 常只缩进约 1.6–1.8 个汉字,且 iOS Safari 15 前存在计算偏差;IE11 及更早版本完全不支持。
32px 在固定字号(如 font-size: 16px)时看似精准,但一旦用户启用系统大字体、浏览器缩放或响应式字号切换(如 @media (prefers-reduced-motion) 下调整),缩进就僵死不变,破坏阅读节奏。
使用 2em 的前提是确保元素有明确的 font-size,避免继承自 font-size: 0 的父容器(常见于 flex 容器重置)。
text-indent 不生效?先查这三类上下文问题
写对了样式却没效果,90% 是块级格式化上下文被破坏:
-
<span></span>、<em></em>这类display: inline元素加text-indent→ 必须显式设display: inline-block或display: block - 父容器是
display: flex,子<p></p>没写display: block→ flex item 默认不触发块格式化上下文,text-indent被忽略 - 段落设置了
white-space: nowrap或display: inline-flex→ 文本无法换行,“首行”概念失效 - 父级有
text-align: justify且该段落只有一行 → 浏览器为对齐末尾可能强制取消缩进,加text-align: left覆盖即可 - 外层
margin-left或padding-left未重置 → 视觉上叠加偏移,需检查 computed 样式确认真实缩进值
如何让首段不缩进、后续段落才缩进?
中文排版惯例是正文第一段顶格,从第二段起才首行缩进。用伪类最干净:
p:not(:first-of-type) {
text-indent: 2em;
}
注意::first-of-type 匹配的是同级中第一个 <p></p>,不是页面首个段落;若首段前有 <h2></h2> 或 <blockquote></blockquote>,它仍会被选中。更稳妥的做法是加 class:
.article-content p {
text-indent: 2em;
}
.article-content p:first-child {
text-indent: 0;
}
别用 margin-left 或 padding-left 模拟缩进——它们移动整段,会破坏“仅首行额外缩进”的排版语义,也容易和列表、引用块等产生对齐冲突。
移动端 Safari 和旧版 IE 的兜底策略
iOS Safari 15+ 对 2em 支持稳定,但若你必须支持 iOS 12–14 或 IE11,建议分层处理:
- 基础层:
text-indent: 2em(所有现代浏览器 + IE6+) - 增强层(可选):
@supports (text-indent: 2ch) { p { text-indent: 2ch; } },覆盖支持者 - 降级层(极少数场景):若字体锁定为
font-size: 16px,可加text-indent: 32px,但必须用@supports not (text-indent: 2ch)隔离,避免干扰 em 计算
真正难搞的不是单位选择,而是嵌套结构里 display 类型的隐式变化——比如一个 <div class="card"> 内部用了 <code>display: grid,再塞 <p></p>,那 <p></p> 就得手动加 display: block 才能唤醒 text-indent。这点最容易被忽略,也最难调试。











