标签不是的替代品,必须嵌套在内且页面中只能有一个;它专用于包裹唯一、不可复用的核心内容,如文章正文,而非导航、页脚等复用模块。

main 标签不是 body 的替代品,它必须嵌套在 body 内
很多初学者误以为 <main></main> 可以代替 ,这是错误的。HTML5 规范明确要求 <main></main> 必须是 的后代元素,且一个页面只能有一个(或零个),不能嵌套使用。
常见错误现象:<main></main> 直接放在 下、多个 <main></main> 并存、在 <header></header> 或 <aside></aside> 里再包一层 <main></main> —— 这些都会导致语义失效,影响屏幕阅读器识别和 SEO 权重分配。
-
是文档主体容器,所有可见内容都必须在其内;<main></main>是其中唯一标识「核心内容」的语义区块 - 没有
<main></main>不报错,但会丢失辅助技术对主内容的快速定位能力 - 服务端渲染(SSR)或静态站点生成器中,若框架自动包裹 layout,需检查是否意外把
<main></main>包进了<header></header>或<nav></nav>
什么时候该用 main,什么时候不该用
判断依据只有一个:这部分内容是否「对当前页面具有唯一性、不可被其他页面复用」。比如文章正文、产品详情、搜索结果列表——这些是 <main></main> 的典型场景;而导航栏、页脚版权、侧边广告位、面包屑导航,哪怕它们在视觉上位于页面中央,也不属于 <main></main>。
容易踩的坑:<main></main> 里塞了全局 <nav></nav> 或重复使用的 <aside></aside>;或者把整个单页应用(SPA)的根容器(如 <div id="app">)直接当成 <code><main></main> —— 实际上,只有路由切换后真正变化的那块内容才应被包裹。
立即学习“前端免费学习笔记(深入)”;
- ✅ 正确:
<main> <article> <h1>如何正确使用 main 标签</h1> <p>这是本页唯一的核心内容...</p><div class="aritcle_card flexRow"> <div class="artcardd flexRow"> <a class="aritcle_card_img" href="/ai/1992" title="Play.ht"><img src="https://img.php.cn/upload/ai_manual/001/246/273/68b6cfb01526f399.png" alt="Play.ht" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a href="/ai/1992" title="Play.ht">Play.ht</a> <p>根据文本生成多种逼真的语音</p> </div> <a href="/ai/1992" title="Play.ht" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> </article> </main> - ❌ 错误:
<main> <header><nav>...</nav></header> <article>...</article> <footer><p>©2024</p></footer> </main>
- 动态页面中,
<main></main>应随路由更新而重新挂载,而不是固定包裹整个 SPA 容器
与 aria-main 和 role="main" 的关系
如果因历史原因无法修改 HTML 结构(比如 CMS 输出固定模板),可以用 role="main" 或 aria-labelledby 做语义补充,但优先级低于原生 <main></main>。W3C 明确建议:已有 <main></main> 就不要加 role="main",否则可能触发双重播报(double-announced)问题。
真实调试中,用浏览器开发者工具的「Accessibility Inspector」查看「Landmark」区域,能立刻验证 <main></main> 是否被正确识别。若未出现,大概率是嵌套层级错误或被 JavaScript 动态移除。
- 避免写:
<main role="main"></main>—— 属于冗余且有潜在兼容风险 - 旧项目升级时,若存在
<div role="main">,应逐步替换为 <code><main></main>,而非共存 - 某些老旧屏幕阅读器(如 JAWS 16 及更早)对
<main></main>支持不完整,此时可保留aria-label作为降级方案:<main aria-label="主要内容"></main> - Next.js 中,
<main></main>应放在app/layout.tsx的{children}外层,而非每个page.tsx内部重复定义 - 若使用
next/head或<title></title>动态更新,确保<main></main>内容与<title></title>语义一致(例如标题写「产品 A 详情」,则<main></main>内第一级标题也应匹配) - 构建产物中搜索
<main></main>出现次数,确认只有一处且位置合理 —— 自动化 lint 工具如 axe-core 或 html-validate 可加入 CI 检查
SEO 和 SSR 中容易被忽略的细节
搜索引擎爬虫目前普遍支持 <main></main>,并将其作为内容相关性加权的重要信号。但如果你用 Next.js、Nuxt 或 Remix 等框架,要注意:服务端生成的 HTML 中,<main></main> 必须包含实际内容,不能是空标签或仅含 loading 占位符。
另一个隐形陷阱:CSS 重置或 UI 框架(如 Bootstrap)可能给 main 元素设了默认 display: block 以外的值(例如 display: contents),这会导致无障碍树中该节点“消失”。务必检查 computed styles。









