<p>、<div>、<section>、<script>、<textarea>、<select>等必须显式闭合,不闭合会破坏DOM结构,导致内容错位、JS不执行、样式失效或无障碍访问受损。

哪些标签必须显式闭合,不闭合会出什么问题
像 <p>、<div>、<section>、<script>、<textarea>、<select> 这类标签属于 “normal elements”,HTML 规范要求必须写结束标签。不闭合不是“浏览器帮你补”,而是直接破坏 DOM 结构。
常见错误现象:
-
<p>Hello<span>world</span>—— 后续所有内容都会被当成这个未闭合<p>的子节点,直到遇到下一个<p>或块级元素才可能被“强制截断” -
<script>console.log(1)</script>写成<script />—— JS 完全不执行,控制台静默,连语法错误都不报 -
<textarea>default text</textarea>写成<textarea />—— 输入框变成空的,value属性失效,placeholder 也不显示
哪些标签根本不能写结束标签
<img>、<input>、<meta>、<link>、<hr>、<br> 属于 void elements(空元素),它们在 HTML5 中没有结束语义。写 <img></img> 或 <input></input> 是非法的,浏览器会忽略后半部分,甚至把后续 HTML 当作该标签的子内容解析。
比如:
立即学习“前端免费学习笔记(深入)”;
<img src="a.jpg"></img> <p>This paragraph may disappear or misalign</p>
实际效果可能是:<p> 被吞进 <img> 的 DOM 树里(虽然渲染不可见),导致样式错乱或 JS 获取不到预期节点。
注意:<img src="a.jpg" /> 看似“整齐”,但斜杠在 HTML 文档中纯属冗余,且在某些模板引擎(如旧版 Vue SFC)或 linter 工具中会引发属性截断——src 可能被当成 src="a.jpg "/ 处理。
<script> 和 <style> 必须闭合,哪怕没内容
这两个标签看似“不包裹可见内容”,但它们的文本子节点就是可执行代码或 CSS 规则。空标签 <script /> 不代表“无脚本”,而是代表“无效脚本容器”——浏览器不会执行任何内容,也不会触发 DOMContentLoaded 相关逻辑。
正确写法只有这一种:
<script></script>
或者带内容:
<script>console.log('loaded')</script>
如果你用构建工具注入脚本(如 Webpack 的 html-webpack-plugin),也要确认它生成的是成对标签,而不是自闭合形式。
为什么有些闭合标签可以省略,但不建议省略
HTML5 允许省略部分结束标签,比如 <li>、<dt>、<dd>、<p>(在特定上下文中)。但这不是“自由发挥”的理由。
容易踩的坑:
- 省略
</p>后,如果下一行是<div>,浏览器会自动闭合<p>;但如果下一行是<em>,就可能继续嵌套,行为难以预测 - 编辑器/格式化工具(如 Prettier)默认不补省略标签,团队协作时容易漏掉,造成渲染差异
- 服务端模板(如 Django、Jinja2)或静态生成器(如 Hugo)可能严格按字面解析,不模拟浏览器容错逻辑
真正安全的做法:所有成对标签都显式写出开始和结束,除非你明确知道当前上下文允许省略,且已验证过目标环境(包括 SSR 和客户端)的行为一致。



















