main标签必须且只能出现一次,否则屏幕阅读器可能跳过或只识别第一个,Lighthouse会报错,搜索引擎可能误提取内容;需确保其为body直接子元素、不嵌套在header/footer/nav中,且内部仅包含随URL变化的页面专属内容。

main 标签必须且只能出现一次,否则语义失效
页面里出现两个 <main></main>,浏览器不会报错,但屏幕阅读器(如 NVDA、VoiceOver)可能跳过全部,或只识别第一个;Lighthouse 会明确报错 Document has more than one main landmark;搜索引擎也可能把页脚版权当成正文提取。常见翻车点包括:
- React/Vue 每个路由组件(
Home.tsx、About.tsx)都写了<main>{children}</main>→ hydration 后 DOM 留下多个<main></main> - Next.js 的
app/layout.tsx里提前塞了<main></main>→ 这是全局壳层,不是页面主体 - 服务端模板循环渲染卡片时,误给每张卡片都包上
<main></main>→ 语义彻底崩坏
main 不能嵌套在 header、footer、nav 里,层级必须平级
HTML5 规范白纸黑字禁止 <main></main> 成为 <header></header>、<footer></footer>、<nav></nav> 或 <aside></aside> 的后代。错误写法如 <header><main></main></header>,会导致读屏软件判定“这是导航上下文里的内容”,直接忽略主区域。
正确结构必须是兄弟级并列,且都为 的直接子元素(或仅包裹在中性 <div> 里):
<pre class="brush:php;toolbar:false;"><body>
<header></header>
<nav></nav>
<main><h1>文章标题</h1><p>正文</p></main>
<footer></footer>
</body></pre>
<p>注意:<code><main></main> 内部可以包含一个 <header></header>,但仅限本页专属标题(如文章 <h1></h1> + 发布时间),不是全站 Logo + 主导航。
立即学习“前端免费学习笔记(深入)”;
main 里该放什么?只放“随 URL 变化、不可复用”的内容
判断标准非常实在:这块内容复制粘贴到另一个页面还能原样用?能 → 就不该进 <main></main>。
- ✅ 允许:
<h1></h1>(页面级标题)、商品列表(<ol></ol>)、独立表单(<form></form>)、文章正文、用户仪表盘核心数据区 - ❌ 禁止:
<nav></nav>(全局导航)、<footer></footer>(版权信息)、<aside></aside>(侧边推荐)、全站搜索框、Logo + 登录入口 - ⚠️ 容易混淆:产品页里的“在线客服”按钮——它服务主题但不构成主题本身,应放在
<section></section>或<aside></aside>,而非<main></main>
SPA 路由中怎么安全更新 main 内容?只换内容,不换标签
关键原则是:<main></main> 实例只存在一个,内容动态替换,而非重复创建。错误做法是每个路由组件都渲染自己的 <main></main>;正确做法是:
- 在根 Layout 组件中声明唯一
<main></main>,用<outlet>(React Router v6)或<router-view>(Vue Router)作为其唯一子节点 - 404 页面等异常状态,不要写
<main>{error ? <NotFound /> : <Page />}</main>,而应控制<main></main>节点本身的渲染与否 - 绝对不要用 JS 整个替换
<main></main>元素(如el.replaceWith(newMain)),只替换其子节点;否则 React/Vue hydration 可能丢弃语义信息
最常被忽略的一点:开发者工具里 Ctrl+F 搜索 <main></main>,必须确认匹配结果只有且仅有 1 对开始/结束标签——哪怕它被 CSS 隐藏或 JS 动态移除,只要 DOM 中存在多个,语义就已破坏。



















