可访问性必须从首行HTML开始构建,lang属性需精确到zh-CN或zh-TW,<main>须为<body>直接子元素且唯一,标题层级不可跳级,语义标签不可用div模拟。

可访问性不是上线前补的补丁,而是从第一行 <html> 就该确定的事。只要 lang 写错、<main> 嵌套、标题跳级,屏幕阅读器用户就可能直接“掉出”页面——这不是体验问题,是结构性失效。
lang 属性必须写对,不能靠“差不多”蒙混过关
写成 lang="zh" 或 lang="cn" 看似省事,但 NVDA、VoiceOver 会把它当无效值处理,中文内容大概率被读成日语或英文,分词错乱、语调崩坏。
-
lang="zh-CN"(简体中文)和lang="zh-TW"(繁体中文)是 IANA 注册的合法值,AT 兼容性有保障 - 多语言段落要嵌套写,比如引文:
<p lang="en">The quick brown fox...</p> - React/Vue 中别用 JS 动态拼接
lang值——SSR 或首屏 HTML 必须带对,否则初始朗读已错 -
<html lang="zh-CN">必须顶格出现在文件最开头,前面不能有任何空格、BOM 或注释
<main> 只能出现一次,且必须是 <body> 的直接子元素
把 <main> 包在 <div class="wrapper"> 里,看似无害,实则会让主流屏幕阅读器(如 NVDA)跳过整个主内容区——它只认 <body><main> 这个直系路径。
- 校验工具(如 axe-core)会直接报
document-has-main严重错误 -
<main>内部不能再嵌套另一个<main>,哪怕只是组件复用也不行 - 如果布局需要外层容器,用
<div role="region" aria-label="主内容">替代包裹,不破坏语义流
标题层级断裂比样式错乱更致命
屏幕阅读器用户按 H 键逐级跳转时,依赖的是 DOM 中真实的 <h1>→<h2>→<h3> 逻辑链。一旦 <h2> 后跟 <h4>,他们就会“坠层”,以为章节结束,实际正文还在继续。
立即学习“前端免费学习笔记(深入)”;
- CSS 隐藏标题(
display: none)比删 DOM 更危险——结构还在,但 AT 无法感知,导致导航错位 - 组件库默认用
<h2>当卡片标题?嵌套在<h2>主区域下就变成 H2→H2,必须手动降级为<h3> - 每个
<section>应以<h2>或更高级别标题开头;若需重置层级,必须显式提供标题,不能靠 CSS 视觉模拟
语义标签不是“锦上添花”,是键盘与 AT 的唯一信标
用 <div role="button"> 模拟按钮,等于亲手拆掉键盘焦点、Enter/Space 触发、状态播报这三根支柱。原生 <button> 自带全部能力,零配置即用。
-
<nav>不是“所有链接的集合”,而是有明确导航意图的区块:主导航、面包屑、页内锚点列表可用;文章末尾的“相关阅读”不属于<nav> - 多个
<nav>必须用aria-label区分,例如:<nav aria-label="主导航">、<nav aria-label="页内目录"> -
<img>缺失alt不只是 SEO 损失,而是让屏幕阅读器用户彻底丢失图像信息;装饰图用alt="",别删属性
最难的不是记住所有规则,而是在写 <div class="card"> 的瞬间,本能地换成 <article>;在加 onclick 时,下意识先想有没有原生语义标签能替代。这种肌肉记忆,才是无障碍真正落地的临界点。



















