<p>标签必须包裹完整语义单元,仅允许嵌套行内元素,段距用margin控制,首行缩进用text-indent: 2em;滥用<p>会导致DOM断裂、样式错位与可访问性问题。

段落必须用 <p> 包裹完整语义单元
不是换行工具,也不是样式占位符。只要内容构成一个逻辑上独立、可被单独理解的文本块,就该用 <p> 包裹——比如“用户提交后,系统将在 5 秒内返回结果。”就是一个合格段落;而“点击”“确认”“完成”这种碎片词,不该各自套 <p>。
常见错误是 CMS 或富文本编辑器把回车直接转成空 <p></p>,它会渲染出带默认 margin 的空白块,导致布局偏移。检查源码时看到连续多个 <p></p>,基本可以判定语义失控。
- ✅ 正确:
<p>注册成功,您现在可以登录账户。</p> - ❌ 错误:
<p>注册成功,</p><p>您现在可以登录账户。</p>(语义割裂) - ⚠️ 危险:
<p><div class="alert">警告信息</div></p>(浏览器自动截断为<p></p><div>...</div><p></p>)
<p> 内只能嵌套行内元素
HTML 规范明确限制 <p> 的内容模型:只允许文本节点、<strong>、<em>、<a>、<img>、<code> 等行内级元素。一旦出现 <div>、<h3>、<ul> 或另一个 <p>,解析器会立即闭合当前 <p>,造成 DOM 结构意外断裂。
比如写 <p>说明如下:<ul><li>支持 JSON 格式</li></ul></p>,实际渲染效果等价于:
立即学习“前端免费学习笔记(深入)”;
<p>说明如下:</p> <ul><li>支持 JSON 格式</li></ul> <p></p>
这会导致样式错位、选择器失效,甚至影响屏幕阅读器播报顺序。
段落间距必须靠 margin 控制,而非 line-height 或 padding
浏览器默认给 <p> 加的是 margin-top 和 margin-bottom(通常各 1em),这是段落间“呼吸感”的来源。想调整间距,就直接覆盖这两个值:
- 全局微调:
p { margin: 0.75em 0; } - 首段去顶边距:
.article p:first-child { margin-top: 0; } - 末段去底边距:
.article p:last-child { margin-bottom: 0; }
用 line-height 拉高来“凑”段距,会让段内行距异常;用 padding 则是在段落内部撑开空间,不解决块级分隔问题,还可能触发不必要的滚动条或盒模型溢出。
首行缩进必须用 text-indent,且优先选 2em
中文排版要求首行缩进两个汉字宽度,text-indent: 2em 是唯一可靠方案。它基于当前字体大小计算,用户放大字号、切换系统 DPI 或启用强制缩放时仍能保持比例一致。
写成 text-indent: 32px 表面看一样,但一旦用户将浏览器缩放设为 150%,或在 2K 屏上使用系统级字体缩放,缩进就会失准——要么太窄像没缩进,要么太宽挤占正文。
注意:text-indent 只作用于首行,不影响后续换行;而用空格或全角空格实现缩进,既不可访问,又容易被 CMS 清洗掉,也不响应字体变化。
<p>,而是守住它的语义边界:当富文本编辑器粘贴进来一堆 <div> 块、当设计师要求“这里多空一行”,当后端模板拼接时忽略闭合标签——这些时刻,<p> 往往第一个被牺牲。它不显眼,但一旦松动,可访问性、SEO、CSS 可维护性都会连锁塌方。



















