<main>只能有一个且不能嵌套在<section>里,因其是页面唯一语义锚点,代表整页不可替代的核心内容;多个或嵌套会导致屏幕阅读器跳转失效、SEO降权及无障碍工具报“landmark-uniq”错误。

为什么只能有一个,且不能嵌套在里
因为浏览器和辅助技术靠main识别全页唯一主内容区——它不是“看起来像主要内容”的容器,而是语义上不可替代的主体锚点。多个main会让屏幕阅读器反复跳转,SEO 也可能把权重分散到错误区块。
嵌套在section里更危险:section本身表示“可独立分发的内容单元”,比如一篇博客、一个评论区;而main是整页的上下文根。两者语义冲突,DevTools 的 Accessibility 面板会直接标为“landmark-uniq”错误。
-
main必须作为body直接子元素(或紧贴在header/nav后) - 如果页面有多个“主要内容块”,比如首页轮播+推荐列表+最新文章,它们应统一包裹在单个
main内,用section或article再分层 - CI 中可用 htmlhint 配置
id-unique和landmark-uniq自动拦截
哪些坚决不能换语义标签
不是所有带 class 的 div 都该动。换错比不换危害更大——比如把 <div class="clearfix"> 强行改成 <nav>,会导致辅助工具误判为导航区,用户按快捷键跳转时直接卡死。
判断依据只有一条:它是否承载**可被机器识别的功能角色**。
立即学习“前端免费学习笔记(深入)”;
-
<div class="wrapper">、<div class="clearfix">、<div class="grid-col"> → 留 div,这是样式/布局胶水,换语义标签等于伪造结构
-
<div class="nav">、<div class="article">、<div class="footer"> → 换,前提是内部内容确实匹配对应语义(如 nav 里只有链接,article 有完整标题+正文+时间)
- 检查 DevTools 的 Elements 面板:右键 → “Accessibility” → 看 Role 是否为
navigation、article 等,不是就说明换错了
用前必须检查有没有–
section 不是“视觉上的一块区域”,而是“逻辑上可独立复用的内容段”。W3C 明确要求:每个 section 应有标题,否则它大概率只是个样式容器,该用 div。
常见翻车现场:<section><p>这里是公司简介</p></section> —— 没标题,爬虫无法判断这段内容的主题,RSS 抓取时可能直接丢弃。
- 标题必须是
h2–h6,且与父级标题连续(比如父 article 用 h2,子 section 就该用 h3)
- 如果内容确实没自然标题(如纯图标导航栏),优先用
nav 或 div,别硬套 section
- VS Code 装 HTMLHint 插件,启用
headings 规则,保存即报错 section without heading
为什么写了nav,屏幕阅读器还是跳不过去
标签写了≠语义生效。最常见原因是内容混杂或隐藏逻辑破坏了可访问性链路。
例如:<nav><form><input type="search"></form></nav> —— form 不是导航,ARIA 角色冲突,辅助工具直接忽略整个 nav 区域。
-
nav 内只能有导航性交互元素:链接(a)、带 role="link" 的按钮、或明确跳转逻辑的 button
- 避免
display: none 或 aria-hidden="true" 包裹 nav,否则它在无障碍树中彻底消失
- 运行
axe-core 扫描,重点看 “navigation” landmark 是否被识别;没识别出来,90% 是内容或属性问题,不是标签名问题
语义化最难的从来不是“怎么写”,而是“写完之后,机器是否真按你想的那样理解”。每次改完,务必打开 DevTools 的 Accessibility 面板,手动模拟一次屏幕阅读器跳转流程——这才是验证是否真的“语义到位”的唯一方式。
不是所有带 class 的 div 都该动。换错比不换危害更大——比如把 <div class="clearfix"> 强行改成 <nav>,会导致辅助工具误判为导航区,用户按快捷键跳转时直接卡死。
判断依据只有一条:它是否承载**可被机器识别的功能角色**。
立即学习“前端免费学习笔记(深入)”;
-
<div class="wrapper">、<div class="clearfix">、<div class="grid-col">→ 留div,这是样式/布局胶水,换语义标签等于伪造结构 -
<div class="nav">、<div class="article">、<div class="footer">→ 换,前提是内部内容确实匹配对应语义(如nav里只有链接,article有完整标题+正文+时间) - 检查 DevTools 的 Elements 面板:右键 → “Accessibility” → 看 Role 是否为
navigation、article等,不是就说明换错了
用前必须检查有没有–
–
section 不是“视觉上的一块区域”,而是“逻辑上可独立复用的内容段”。W3C 明确要求:每个 section 应有标题,否则它大概率只是个样式容器,该用 div。
常见翻车现场:<section><p>这里是公司简介</p></section> —— 没标题,爬虫无法判断这段内容的主题,RSS 抓取时可能直接丢弃。
- 标题必须是
h2–h6,且与父级标题连续(比如父article用h2,子section就该用h3) - 如果内容确实没自然标题(如纯图标导航栏),优先用
nav或div,别硬套section - VS Code 装 HTMLHint 插件,启用
headings规则,保存即报错section without heading
为什么写了nav,屏幕阅读器还是跳不过去
标签写了≠语义生效。最常见原因是内容混杂或隐藏逻辑破坏了可访问性链路。
例如:<nav><form><input type="search"></form></nav> —— form 不是导航,ARIA 角色冲突,辅助工具直接忽略整个 nav 区域。
-
nav内只能有导航性交互元素:链接(a)、带role="link"的按钮、或明确跳转逻辑的button - 避免
display: none或aria-hidden="true"包裹nav,否则它在无障碍树中彻底消失 - 运行
axe-core扫描,重点看 “navigation” landmark 是否被识别;没识别出来,90% 是内容或属性问题,不是标签名问题
语义化最难的从来不是“怎么写”,而是“写完之后,机器是否真按你想的那样理解”。每次改完,务必打开 DevTools 的 Accessibility 面板,手动模拟一次屏幕阅读器跳转流程——这才是验证是否真的“语义到位”的唯一方式。



















