必须且只能出现一次,是html5与wcag 2.1强制要求的唯一语义锚点,须直接位于下;多个或嵌套会破坏屏幕阅读器跳转、触发lighthouse报错,并干扰seo。

页面中只能有一个 <main></main>,且它必须是 的直接子元素——这不是最佳实践,而是 HTML5 规范和 WCAG 2.1 的强制要求。 多个 <main></main> 会让屏幕阅读器无法预测跳转行为,Lighthouse 会报 duplicate-main 错误,搜索引擎也可能降权核心内容识别。
怎么快速确认页面只有一个 <main></main>
浏览器不报错,但错误极易被忽略。必须手动验证:
- 打开开发者工具(F12),在 Elements 面板按
Ctrl+F(Windows)或Cmd+F(macOS),搜索<main></main> - 检查匹配结果:只应出现一对
<main></main>和标签;注意 SPA 场景下组件重复渲染可能留下多个残留实例 - 若发现多个(例如在
<article></article>内、<footer></footer>下方、或服务端模板循环中生成),立即删除冗余项,仅保留包裹当前路由视图核心内容的那一个
<main></main> 为什么不能嵌套在 <header></header> 或 <nav></nav> 里
这不是兼容性问题,而是语义冲突——<main></main> 表示“整页唯一主体”,它不可能“属于”页眉或导航栏。W3C 明确禁止其作为这些元素的后代。
- 错误写法:
<header><main>...</main></header>→ Lighthouse 报The element main must not appear as a descendant of the header element - 正确结构:
<header>...</header><main>...</main><nav>...</nav><footer>...</footer>,所有语义区块并列于下 - 例外:
<header></header>可以作为<main></main>的**直接子元素**,但仅限本页专属标题(如文章<h1></h1>+ 发布时间),不是全站 Logo + 导航
<main></main> 里该放什么、不该放什么
判断标准极简:如果这块内容复制粘贴到另一个页面还能原样用,那它就不该进 <main></main>。 它不看视觉位置或权重高低,只认语义归属。
- ✅ 应包含:文章正文、商品详情、搜索结果列表、表单主体、404 提示文案
- ❌ 必须排除:
<nav></nav>、<footer></footer>、面包屑、版权信息、登录框、“关注我们”模块等全站复用内容 - ⚠️ 容易误判:“热门推荐”是否进
<main></main>,取决于它是否随 URL 动态变化主题;若固定展示,则属于通用模块,应移出
SPA 路由中如何安全更新 <main></main> 内容
关键原则:标签实例只存在一个,内容动态替换,而非重复创建。
- 在根 Layout 组件中声明唯一
<main></main>,用<outlet></outlet>(React Router v6)或<router-view></router-view>(Vue Router)作为其唯一子节点 - 避免在
ArticlePage.tsx和ProfilePage.tsx中各自写<main>{children}</main> - 404 等异常状态,不要靠
<main>{error ? <notfound></notfound> : <page></page>}</main>,而应通过状态控制<main></main>节点本身的渲染与否 - 不要用 JS 整个替换
<main></main>元素,只替换其子节点;否则 SSR 与 hydration 可能错位,导致语义丢失
最常被忽略的点是:开发者工具不报错,Lighthouse 审计也常被跳过;但一旦上线,屏幕阅读器用户就卡在导航里反复 Tab,而你根本收不到反馈。验证唯一性、检查父级、清理内部通用模块——这三步必须成为每次 DOM 上线前的硬性 checklist。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











