必须仅有一个元素,因wcag 2.1规定其为硬性失败项,辅助技术依赖它定位主内容,多个会导致导航混乱;标题需严格层级连续且首个为;表单控件须用for/id显式关联;动态内容需正确配置aria-live等属性。

为什么只能有一个,多了会直接被axe报错
WCAG 2.1 的 Multiple 'main' elements 错误不是警告,是硬性失败项。辅助技术(如 NVDA、VoiceOver)依赖 <main></main> 作为页面主要内容的唯一锚点,多个 <main></main> 会让 AT 无法判断“哪里才是主内容”,键盘用户按 M 快捷键也会随机跳转或失效。
- 检查方式:用 axe 浏览器插件扫描,或运行
npx axe-cli http://localhost:3000 - 常见误用场景:SSR 框架中组件重复渲染
<main></main>;模板继承时父模板和子模板都写了<main></main> - 修复动作:全局搜索
<main>,确保只在顶层布局文件(如 <code>_layout.njk或App.tsx)中出现一次,所有子页面用<section></section>或<article></article>划分内容块
标题层级断层(比如→)会让屏幕阅读器用户丢失上下文
)会让屏幕阅读器用户丢失上下文
标题不是 CSS 样式选择,而是 DOM 逻辑树。屏幕阅读器用户靠 H 键循环跳标题来快速导航,一旦跳级(如从 <h2></h2> 直接到 <h4></h4>),AT 就会认为中间存在“隐藏章节”,直接跳过——用户根本不知道自己漏看了什么。
- 每个页面严格一个
<h1></h1>,且必须放在<header></header>内,代表整个页面主题 -
<main></main>内第一个标题必须是<h2></h2>,不能是<h1></h1>(否则触发 WCAG 2.4.6) - 禁止用
<p class="title-h2"></p>模拟标题——AT 完全无视,只会读成普通段落 - Eleventy/Nunjucks 模板中,建议用宏统一控制标题层级:
{% macro heading(level, text) %}<h level>{{ text }}</h>{{ level }}>{% endmacro %},避免手写出错
表单没用
视觉上对齐的 <input> 和旁边 <span>用户名</span> 对 AT 来说毫无关系。没有显式关联,焦点落在输入框上时,屏幕阅读器只会说“编辑框”,不会告诉你“这是用户名输入框”。这不是体验问题,是功能缺失。
- 必须用
<label for="username"></label>+<input id="username">配对,for和id值严格一致 - 单选/复选组必须套
<fieldset></fieldset>+<legend></legend>,<legend></legend>是整组的可访问标题,不可省略 - React 中若用受控组件,别忘了给
input加aria-labelledby指向对应id的说明元素 - FastUI 或 Eleventy 插件如
eleventy-plugin-a11y可自动检测未绑定的表单控件,但不能替代手动验证
动态加载内容(如搜索建议)不加 aria-live,AT压根不知道更新了
AJAX 加载的下拉建议、实时校验提示、模态框内容,如果没声明 aria-live,屏幕阅读器就像“看不见”一样继续静默——用户输完字,等不到反馈,也不知道是否提交成功。
- 推荐值:
aria-live="polite"(适合非紧急内容),aria-live="assertive"仅用于错误弹窗等中断性提示 - 必须配合
aria-atomic="true"(整块更新)或aria-relevant="additions text"(只读新增文本) - 不要把
aria-live放在顶层——会导致全站更新都被播报;应紧贴动态区域,如<div aria-live="polite" aria-atomic="true"></div> - wkhtmltopdf 生成 PDF 时,
aria-live会被忽略,所以 PDF 场景需另用结构化语义(如<section aria-label="搜索结果"></section>)替代
<nav></nav>,而是改完后没逐项验证:是否所有 <main></main> 都只剩一个?是否每个 <section></section> 都有对应标题?是否每个 <input> 都被 <label></label> 或 aria-labelledby 显式关联?这些点不手动点开 axe 报告一条条核对,自动化工具扫不出全部问题。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











