<main>是HTML5中唯一标识页面“当前视图核心内容”的语义标签,必须且只能出现一次,用于界定与URL主题强相关、不可复用的独有内容,是屏幕阅读器跳转主内容的唯一锚点,多个会破坏可访问性。
<main></main> 是 HTML5 中唯一标识页面“当前视图核心内容”的语义标签,不是视觉容器,也不是可选装饰——它直接决定屏幕阅读器跳转路径、搜索引擎摘要提取范围,以及 Lighthouse 等工具的无障碍评分。
<main></main> 会破坏可访问性辅助技术(如 NVDA、VoiceOver)把 <main></main> 当作“按 M 键直达主内容”的唯一锚点。一旦出现两个,读屏器可能随机选一个、跳过全部,或反复播报“主内容开始”,用户完全无法预测行为。
<main>{children}</main> → 实际 DOM 留下多个 <main></main>,Lighthouse 报 duplicate-main
<main></main> 包裹逻辑 → 渲染出嵌套或并列的多个<main></main>,什么必须踢出去<main></main> 只收“这个页面独有、不可复用、与 URL 主题强相关”的内容。它不看位置,只看语义归属。
<section></section> 更合适<main></main>
React/Vue 里最稳妥的做法是:只在根 Layout 组件中声明一次 <main></main>,所有子路由内容作为其直接子节点动态替换,而不是让每个页面组件自己渲染一个 <main></main>。
立即学习“前端免费学习笔记(深入)”;
<outlet></outlet> 套在 <main></main> 内,或 Vue Router 的 <router-view> 作为 <main></main> 唯一子元素ArticlePage 里写 <main><Article /></main>,又在 ProfilePage 里重复 —— hydration 后 DOM 中残留多个<main>{error ? <NotFound /> : <Page />}</main>,要确保整个应用生命周期内 <main> 节点只存在一个实例,可通过状态控制是否渲染该节点本身IE 完全不识别 <main></main> 的语义,但能渲染为普通块级元素;真正的问题出在 CSS 和动态创建上。
main { display: block; },否则 IE8 及更早版本会忽略规则document.createElement('main') 动态插入(非 SSR 输出),需手动加 role="main" 补充语义<main></main> 可能延迟识别甚至忽略,优先走 SSR 或 hydration 初始化<main> 和 <div role="main"> 同时存在时,部分辅助技术会优先响应后者,导致原生语义失效最难的从来不是怎么写 <main></main>,而是每次路由跳转、CMS 模板渲染、甚至 A/B 测试分支上线时,你有没有重新审视:“此刻 DOM 中,到底哪个区块才配叫‘主’?”