语义标签本身不损害性能,关键在于必要处使用;仅当区块含h2及以上标题时section才具实际语义价值,否则与div等价;main必须唯一且不可嵌套于article或section内;深层嵌套易引发样式绑定、渲染开销及无障碍问题。

语义结构不是性能的敌人,但盲目堆砌语义标签会拖慢渲染、增加维护负担——关键在“必要处用必要标签”,而不是“能用就用”。
什么时候该用 <section> 而不是 <div>
单独一个没标题的 <section> 和 <div> 在可访问性、SEO、JS 查询上完全等价,纯属多写两个字符。
- 只有当区块内有
<h2>或更高级别标题时,<section>才产生实际语义价值:屏幕阅读器靠它生成文档大纲,搜索引擎靠它识别内容主题 - 商品列表页里每个卡片用
<article>是合理的(独立、可分发、可订阅),但用<section>包裹整个列表反而削弱语义——列表本身不是“主题区块”,而是容器 - 如果 JS 里写
document.querySelectorAll('section')来取数据,而实际结构是<div class="product-list">...</div>,那改类名就崩;换成document.querySelector('[data-module="product-list"]')更稳
<main> 必须唯一,且不能嵌套在 <article> 或 <section> 里
W3C 明确规定每页只能有一个 <main>,且它代表整个页面的主体内容。把它塞进 <article> 里,等于告诉辅助技术“这篇文章才是整页核心”,和事实冲突。
- 常见错误:
<article><main>...</main></article>—— axe 工具会直接报region-missing和landmark-is-top-level错误 - 正确做法:
<main><article>...</article><article>...</article></main> - 动态渲染时尤其注意:SSR 渲染出多个
<main>,或客户端 hydrate 后重复挂载,会导致无障碍树错乱,键盘焦点跳转异常
嵌套三层以上就该检查是否真需要语义,还是只是习惯性套壳
浏览器解析 HTML 是流式单线程,每多一层嵌套,就多一次 DOM 节点创建 + 样式计算开销。但真正伤性能的不是“三层”这个数字,而是深层结构催生的副作用。
立即学习“前端免费学习笔记(深入)”;
- 检查 CSS 是否大量出现
nav ul li a这类依赖位置的选择器——说明结构本身在绑架样式,一改布局就得翻 CSS - iOS Safari 对超过 5 层嵌套的 flex 容器实测帧率明显下降,不是理论值,是滚动卡顿的临界点
- Chrome DevTools → Elements 面板里右键节点选 “Break on → Attribute modifications”,能快速暴露被 JS 反复 patch 的冗余包裹层
- 单个父容器下子元素超 50 个(比如商品列表、评论流),样式计算时间非线性增长,此时优先用
DocumentFragment批量插入,而非逐个appendChild
用 data-module 替代类名锚定 JS 模块,比语义标签更可靠
语义标签解决的是“结构意图”,但 JS 绑定逻辑常需要精确命中某个功能模块——而 <header> 可能被复用在页头、文章头、弹窗头,光靠标签无法区分。
- 给根容器加
data-module="search-bar"、data-version="2.1",CI 流程可自动校验 HTML 片段是否匹配当前组件版本 - 避免用
id做模块标识:循环渲染商品卡片时,id="product-item"必然重复,document.getElementById()只返回第一个 - JS 查询统一走
document.querySelectorAll('[data-module="header"]'),不依赖类名、不依赖嵌套深度、不依赖语义标签是否存在
真正难的不是“该不该用语义标签”,而是判断哪一层结构承担了真实语义责任、哪一层只是为布局妥协留下的技术债——这两者混在一起时,DOM 就开始悄悄变重。



















