text-indent: 2em是中文首行缩进推荐方案,但仅对块级元素生效;失效主因包括元素非块级、white-space压制首行、内联元素干扰起点、flex/grid格式化上下文抑制及高权重样式覆盖。

text-indent 是唯一语义正确、浏览器原生支持的首行缩进手段,但它不是“加了就生效”的傻瓜属性——它只对块级元素起作用,且极易被布局、单位、继承关系干扰。
为什么 text-indent: 2em 加在 <p> 上却没效果
这不是 CSS 写错了,而是浏览器压根没把它当“段落”处理:
- 目标
<p>的 computeddisplay值是inline或inline-flex(比如被父容器设为 flex item 后未显式重置) - 父容器用了
white-space: nowrap或pre,整段被压成单行,“首行”概念失效 - 段落开头嵌了
<img>或<svg>,浏览器把该内联内容当作“首行起始”,缩进发生在它左边——视觉上等于没动 - 某处更高权重样式写了
p { text-indent: 0 }(常见于重置样式表或富文本编辑器输出的内联style)
text-indent 单位选 em 还是 ch 还是 px
中文排版要的是“两个汉字宽度”,但不同单位行为差异很大:
-
text-indent: 2em:推荐首选。1em = 当前元素font-size,缩进随字号缩放,响应式友好;但注意:em 是字体大小,不是字符宽度,等宽字体下可能偏宽 -
text-indent: 2ch:更贴近语义(1ch ≈ 数字0的宽度),多数中文字体下单字接近 1ch,但 IE 不支持,且依赖字体度量精度 -
text-indent: 32px:仅适合字体大小绝对固定、无无障碍缩放需求的场景;系统放大字体时会失准 -
text-indent: 2%:按父容器宽度计算,和字体完全无关,缩进可能大得离谱(比如父容器宽 1000px,2% 就是 20px,而字体才 14px)
Flex/Grid 容器里 text-indent 失效怎么办
当 <p> 是 display: flex 或 display: grid 的直接子项时,text-indent 常静默失效——这不是 bug,是格式化上下文限制。
立即学习“前端免费学习笔记(深入)”;
- 首选方案:
padding-left: 2em。它不依赖“首行”语义,对 flex item / grid item 同样生效,视觉结果几乎一致 - 硬要用
text-indent:给<p>显式加display: block,并检查是否被align-self或justify-content拉偏位置 - 别在导航菜单、卡片标题这类本就不该有“段落缩进”语义的地方硬套
text-indent;那是间距问题,该用margin-left或padding-left
容易被忽略的继承与边界行为
text-indent 有继承性,但继承的是声明值,不是计算值——这意味着嵌套块级元素可能意外叠加缩进:
- 父
<div>设了text-indent: 2em,里面再套一个<p>,若没重置,<p>会缩进 4em(2em 继承 + 自身 2em) - 负值合法(
text-indent: -1em),但若没配padding-left,文字可能被缩到容器外,且overflow: hidden会裁掉它 -
text-indent缩进的是内容盒(content box),不包含padding区域;如果你期望文字离边框也有距离,得额外加padding-left -
<textarea>和contenteditable区域里,text-indent完全不生效——这类区域的换行和缩进由用户输入控制



















