应使用语义化标签替代div布局,如header、nav、main等,因其自带role属性且能被屏幕阅读器正确识别;main只能出现一次且不可嵌套;多导航需用aria-label区分;避免视觉隐藏破坏可访问性;确保DOM顺序与逻辑一致;合理使用ARIA补充而非替代语义。

用语义化标签替代 div 布局
屏幕阅读器不靠视觉样式理解页面,而是解析 DOM 结构和可访问性树。一堆嵌套的 <div> 会让它只读出“division”,完全无法区分导航、主内容或页脚。
必须把 <div class="header"> 换成 <header>,<div class="nav"> 换成 <nav>,<div class="main"> 换成 <main>。这些标签自带角色(role),无需额外 ARIA 就能被 NVDA、VoiceOver 正确识别。
-
<main>页面中只能出现一次,且不能嵌套在<article>或<section>内 -
<nav>若页面含多个导航区(如页眉+侧边栏),需加aria-label区分,例如aria-label="主导航" - 避免用
<div>包裹语义标签做布局(如<div class="wrapper"><header>...</header></div>),这不会破坏语义,但徒增冗余节点
正确使用 aria-labelledby 和 aria-label 补充语义
当原生标签不足以表达意图时,ARIA 是必要补充,但不是替代方案。比如一个仅含图标的按钮,没有可见文本,aria-label 就是刚需;而一个复杂表格,标题在上方但未用 <caption>,就得靠 aria-labelledby 关联。
关键区别:aria-label 直接提供名称,会覆盖元素内文本;aria-labelledby 引用其他元素的文本,适合复用已有内容。
立即学习“前端免费学习笔记(深入)”;
- 不要给
<img>同时设alt和aria-label,优先用alt—— 这是第一道语义防线 - 表单控件必须用
<label for="id">或包裹方式显式关联,仅靠视觉对齐 +aria-label不可靠 -
aria-describedby适合指向辅助说明(如错误提示),但内容不能太长,否则屏幕阅读器会一次性朗读全部
避免用 CSS 隐藏破坏可访问性
display: none 和 visibility: hidden 会让元素彻底从可访问性树中移除,这是安全的隐藏;但 overflow: hidden、height: 0、clip-path 等仅视觉隐藏的方式,DOM 仍存在,屏幕阅读器照读不误。
典型踩坑场景:评论卡片“展开/收起”功能用 max-height + overflow: hidden 控制,收起状态下 NVDA 仍朗读全部截断文本。
- 动态折叠内容,首选原生
<details><summary>—— 它自动管理aria-expanded和焦点,无需 JS 即可工作 - 若必须自定义,收起时应同时设
aria-hidden="true"和aria-expanded="false",展开时同步更新 - 绝对定位 +
left: -9999px属于“视觉隐藏但可聚焦”,容易导致键盘焦点丢失,慎用
确保 DOM 顺序与逻辑顺序一致
屏幕阅读器按 HTML 文档流顺序朗读,不是按 CSS 布局顺序。用 flex 或 grid 的 order 属性调换视觉位置,但 DOM 顺序没变,会导致阅读混乱。
例如:导航在视觉上放底部,但 HTML 中写在 <main> 后面,屏幕阅读器用户就得先听完全部正文才听到导航。
- 移动端尤其要注意,响应式切换常靠 CSS 重排,但 DOM 应保持“导航 → 主内容 → 页脚”的自然流
- 用
tabindex="0"让非可聚焦元素(如<div>)获得焦点时,必须同步保证其语义合理,否则会破坏阅读节奏 - 动态插入的内容(如搜索结果、通知),要用
aria-live="polite"区域包裹,但区域内部结构要稳定,避免频繁重渲染导致朗读中断
clip-path 隐藏内容;标签语义对了,但 <main> 被包在两个 <div> 里还加了 role="main" —— 多余的 ARIA 反而干扰辅助技术。可访问性不是加属性越多越好,而是让机器能按人的方式理解页面。



















