main 元素必须唯一且为 body 的直接子元素,嵌套或重复会导致 axe 报错、屏幕阅读器跳过及 seo 降权;section 需配 h2+ 标题,article 须自包含可分发;img、input、链接等有严格可访问性要求;data-* 比 class 更适合 js 绑定。

main 只能出现一次,嵌套或重复会直接导致 axe 报错 ARIA: main landmark is not unique,屏幕阅读器跳过、SEO 降权都是确定后果。
为什么 main 不能嵌套在 nav 或其他语义容器里
W3C 明确规定 main 表示页面中“唯一、独立、可分发”的主体内容。一旦被 nav、header 或另一个 main 包裹,语义就坍塌了:
- 浏览器和 axe 工具会报错,CI 流程可能直接拦截构建
- 屏幕阅读器忽略内部的
main,用户无法通过快捷键(如 Ctrl+Alt+O)跳转到主内容 - 搜索引擎可能判定该区域为非核心内容,降低权重
-
main必须是body的直接子元素,合法子元素包括header、section、article,但不能是div包裹层
section 和 article 到底怎么选
不是看视觉是否“分块”,而是看内容是否有独立主题和可分发性:
-
article:内容自包含、可独立传播(如一篇博客、一条新闻、一个用户评论),自带隐式 ARIA role="article" -
section:有明确主题的逻辑区块,且必须配h2或更高阶标题,否则 axe 会警告Section lacks heading - 纯装饰性分隔、仅靠 padding 实现的空白区,不使用任何语义标签,用 CSS 控制
- 后台管理系统多个“主视图”?别硬塞进一个
main,应按路由拆分,每个视图有自己的main;若必须动态切换,用role="main"+aria-live是退化方案,优先重构
图像、表单、链接的可访问性硬性要求
这些不是“建议”,而是 WCAG AA 合规的底线,漏掉一项就可能被无障碍审计工具标红:
-
img必须有alt属性:功能性图像写描述,装饰性图像写alt="" -
input必须有显式关联的label(用for/id或包裹方式),否则input-requires-label规则失败 - 邮件链接必须用
mailto:协议,不能只写邮箱字符串;外部链接建议加rel="noopener noreferrer" - 所有交互元素(按钮、链接、输入框)必须支持键盘 Tab 导航,并有可见的
:focus样式 - 文本与背景对比度 ≥ 4.5:1(正常文本),用 axe 或 WAVE 工具扫一遍比肉眼判断可靠得多
data-* 属性比 class 更适合 JS 模块绑定
用 class="js-modal-close" 做 DOM 查询,等于把样式逻辑和功能逻辑锁死:
- 设计师改个组件名、CSS-in-JS 库升级、BEM 命名调整,
js-类名可能还在,但 JS 绑定已失效 - 推荐用
data-module="modal"+data-action="close",JS 中统一查document.querySelector('[data-module="modal"][data-action="close"]') -
id禁止用于模块标识——列表循环渲染时必然重复,document.getElementById()只返回第一个 - 嵌套超过三层
div就该警觉:.content可能命中弹窗里的同名 class,而main section article p这种路径又太脆弱
最常被忽略的其实是 main 的位置和 section 的标题绑定——它们不是“写了就行”,而是必须满足结构约束才能被辅助技术真正识别。axe 报错不是提示你“可以优化”,是在告诉你:这部分内容对视障用户已经不可用了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











