<main> 必须是 <body> 的唯一直接子元素,重复或嵌套会导致 DOM 查询失败、SSR 水合错误;<nav> 仅用于主导航,滥用会干扰辅助技术与样式;<section> 需带标题,<article> 应为独立内容单元,混用影响 SEO 与可访问性。

必须是 <body> 的直接子元素,且只能出现一次——这是最常被忽略、也最容易引发 bug 的硬性约束。错用语义标签本身不会让页面“白屏”,但会悄悄埋下可访问性中断、SEO降权、CSS选择器失效、甚至 JS DOM 查询错位的隐患。
为什么 <main> 重复或嵌套会导致 DOM 查询失败
很多前端逻辑依赖 document.querySelector('main') 获取主内容容器。一旦页面中出现两个 <main>,或把它写在 <header> 里,结果就不可控:
-
querySelector只返回第一个,后续操作可能作用于错误区块 -
querySelectorAll('main').length返回 2,但业务代码只按 1 处理,漏掉一半内容 - 某些 SSR 框架(如 Next.js)在 hydrate 阶段比对 DOM 时,会因语义结构不合法直接抛错或跳过渲染
<nav> 不是“有链接的地方就用”,而是“主导航才用”
把所有含链接的区域都套上 <nav>,看似“更语义”,实则触发辅助技术误判:
- 屏幕阅读器用户按 N 键跳转导航,结果弹出侧边栏、页脚、弹窗里的三处“导航”,失去快捷入口意义
- Lighthouse 报
navigation-has-sufficient-link-text警告,因为非主导航区域没配aria-label或标题 - CSS 写
nav ul本意是样式主导航菜单,结果连页脚版权链接也被影响
<section> 和 <article> 混用会破坏内容权重判断
搜索引擎和 Lighthouse 都依赖这两者区分“主题分组”与“独立单元”:
立即学习“前端免费学习笔记(深入)”;
-
<section>必须有标题(<h2>或以上),否则会被视为无效语义;而<article>本身自带隐含主题,可独立分发(RSS、分享卡片) - 把一篇博客正文包进
<section>,它就失去了被 RSS 抓取为独立条目的能力 - 把多个产品卡片用
<article>包裹,但每张卡没<h3>标题,Lighthouse 会报article-has-heading错误
class 命名冲突 vs. 语义标签天然隔离
用 <div class="nav"> 写导航,搜索 .nav 可能匹配到五个地方;换成 <nav>,DOM 层面就天然唯一:
- JS 里
document.querySelectorAll('nav')结果确定、可预期 - CSS 中
nav > ul > li a不会意外命中<footer class="nav">里的链接 - 多人协作时,没人敢往
<main>里塞页脚内容——标签本身构成隐性契约
语义标签不是靠“看起来规范”减少 bug,而是靠浏览器解析规则、辅助技术逻辑、SEO 爬虫策略共同形成的硬性约束。一旦违反,问题往往不在控制台报错,而在用户看不见的地方悄然发生。



















