<main>必须且只能出现一次,是页面唯一主内容语义锚点,不得嵌套于<header><nav><footer>等元素内,否则触发axe/Lighthouse报错;电商首页常见错误是<main>被误置于<header>内部,需确保其为<body>直接子元素。

WCAG 无障碍达标率低,往往不是因为缺工具或没标准,而是语义误用、结构越界、动态内容失管这三类问题反复踩坑。真正卡住团队的,是那些“看着合规、跑起来报错”的细节。
main 标签只能出现一次且不能嵌套
这是 W3C 强制规则,也是 axe、Lighthouse 等工具报 duplicate-main 或 main-in-main 错误的直接原因。电商首页最常见错误:把 <main></main> 写在了 <header></header> 或 <nav></nav> 内部,导致结构层级断裂。
- 检查方法:DevTools → Elements → 搜索
main,确认它必须是的**直接子元素**(层级为 2) - 服务端模板(如 Nunjucks)中,禁止在 partial 里输出
<main></main>;只允许 layout 模板定义一次 - CI 流程中加
html-validate规则:"no-duplicate-main": "error"和"no-main-in-main": "error"
section 必须自带标题,否则不如用 div
<section></section> 不是“带语义的容器”,而是“有独立主题、可单独分发的内容区块”。电商页大量误用:商品列表容器、筛选栏、推荐位全套 <section></section>,但里面没有 <h2></h2>~<h6></h6>,反而干扰屏幕阅读器理解主次关系。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
- 正确写法:
<section><h2>热销商品</h2><ul class="product-list"></ul></section> - 错误场景:商品卡片循环渲染时,每个卡片外层用
<section></section>—— 单张卡片不构成独立主题,应改用<article></article>或纯<div> <li>CI 中可用 <code>remark-lint插件拦截:remark-lint-heading-has-content+remark-lint-no-unused-definitions -
alt=""和不写alt有本质区别:不写会触发读屏朗读文件名或跳过不报,alt=""是明确声明“装饰性”,符合 WCAG - 图标按钮(如 ✕ 关闭)必须用
aria-label,不能只靠视觉符号;<button>✕</button>本身无意义,读屏只会读“乘号” - 表单控件禁用
placeholder当标签;首选显式绑定:<label for="email">邮箱地址</label><input id="email"> - NVDA + Firefox(Windows)、VoiceOver + Safari(macOS/iOS)是最低测试组合
- 重点测三类场景:键盘导航全程不依赖鼠标、屏幕关闭下语音控制(Android TalkBack)、高对比度模式下的文字可读性
- 特别注意动态区域更新:如搜索建议列表、购物车数量变化,需加
aria-live="polite"并确保内容更新后能被读出
alt 和 label 必须覆盖所有动态生成节点
服务端渲染或 JS 动态插入的图片、表单控件,若漏掉 alt 或未绑定 <label for="id">,对屏幕阅读器用户就是功能黑洞——不是体验差,是根本不可用。
立即学习“前端免费学习笔记(深入)”;
真实读屏测试比任何校验都关键
所有自动化工具(axe、Lighthouse)只能查出约 30% 的可访问性缺陷。剩下 70% 出现在交互流中:模态框打开后焦点是否落在第一个可操作元素?关闭后是否回到触发按钮?Tab 键顺序是否符合视觉流?这些必须用真实环境验证。


















