<main> 标签无需添加 role="main",浏览器已自动注入该角色;页面只能有一个 <main> 元素,否则破坏 landmark 结构;其内不可包含导航、页脚等非主内容,仅限文章、列表等独立主体内容;IE11 等旧环境应使用 <div role="main"> 而非给 <main> 加 role。

main标签加role="main"是冗余操作
浏览器已经为 <main> 自动注入 role="main",再手动加上不仅没用,还暴露对语义机制的理解偏差。部分旧版 JAWS 会因此重复播报“主内容开始”,干扰用户。Lighthouse 不报错但 axe 工具可能标记为“隐式角色被覆盖”,属于可访问性维护隐患。
多个main元素会导致landmark结构崩溃
WCAG 2.1 明确要求每页仅一个 main landmark。SPA 中常见错误是每个路由组件都渲染独立的 <main>,hydration 后 DOM 中残留多个实例。NVDA/VoiceOver 在按 M 键跳转时可能随机选中、跳过全部,或反复播报,行为完全不可预测。
- React Router v6 正确做法:
<main><Outlet /></main>放在根 Layout,子组件不带<main> - Vue Router 同理:只在
<router-view>外层套一次<main> - 服务端模板需做条件判断,避免列表页和详情页共用同一段包裹逻辑
main里混入导航/页脚等非主内容会破坏语义边界
<main> 不是视觉容器,它定义的是“可独立分发的内容主体”。把 <nav>、<footer> 或侧边栏塞进去,等于告诉屏幕阅读器“这些也是主内容”,直接污染 landmark 导航路径。
- ✅ 允许:
<article>、<ol>(商品列表)、纯文本段落、独立表单 - ❌ 禁止:
<header>(网站级头部)、<nav>、<aside>、<footer> - ⚠️ 注意:
<header>作为文章标题区出现在<main>内是合法的,但必须是内容级 header,不是全局 header
IE11等老环境需要的是div+role="main",不是加role
现代项目基本不用兼容 IE,但若真遇到必须支持的场景,应使用 <div role="main"> 并自行确保唯一性,而不是给 <main> 加 role="main"。前者是兜底方案,后者是语义污染。
立即学习“前端免费学习笔记(深入)”;
- 不要写:
<main role="main"> - 要写(仅限 IE):
<div role="main">+ polyfill 脚本(如 html5shiv) - 验证方式:Chrome DevTools → Accessibility 面板 → 点击元素,Computed Role 应显示
main,而非generic
最容易被忽略的一点:<main> 没有默认样式,也不影响布局流——它纯粹是语义锚点。很多人试图靠它“撑开高度”或“统一外边距”,结果发现它既不触发 BFC,也不自带 margin/padding,纯属白忙活。



















