语义化标签是屏幕阅读器理解页面结构的唯一可靠依据;不用<nav><main><header>等标签,屏幕阅读器只能读“div、div、div”,无法跳转或识别区域意图;<div>和<span>无内置语义,屏幕阅读器默认不播报其存在;<button>自带焦点、触发和禁用逻辑,而<div role="button">需手动补全多项交互支持;<main>是页面主体内容的强制性地标,一个页面仅能有一个且不可嵌套,缺失将导致用户平均下拉7–12次才能定位正文。

语义化标签不是“增强支持”,而是屏幕阅读器理解页面结构的**唯一可靠依据**。不用 <nav>、<main>、<header> 这类标签,屏幕阅读器就只能读出一堆“div、div、div”,无法跳转、无法识别区域意图、也无法建立内容层级。
为什么 <div> 在屏幕阅读器里等于“沉默”
<div> 和 <span> 是纯容器,没有内置语义。屏幕阅读器默认不播报其存在,也不提供导航快捷键(比如 NVDA 的 D 跳 div、H 跳标题——但那是弱线索,不可靠)。它只朗读其中的文本,且不说明上下文。
- 错误示例:
<div class="nav"><a href="/home">首页</a></div>→ 屏幕阅读器只读“首页”,用户不知道这是导航区,也无法用快捷键跳过整个导航栏 - 正确写法:
<nav aria-label="主导航"><a href="/home">首页</a></nav>→ 朗读为“主导航,链接 首页”,并支持N键直接跳入/跳出 - 注意:
<nav>自带role="navigation",无需手动加;但多个<nav>时必须用aria-label或aria-labelledby区分,否则所有导航都叫“导航”
<button> 和 role="button" 的实际行为差异
二者在屏幕阅读器中播报效果可能相似,但交互能力天差地别:
-
<button>:自动获得键盘焦点、空格/回车触发、disabled状态自动禁用交互与朗读、自带 focus outline 样式 -
<div role="button" tabindex="0">:需手动补全tabindex="0"、onkeydown监听空格/回车、aria-disabled管理禁用状态、CSS 处理焦点样式——漏一项,键盘用户就卡住 - 真实坑点:React/Vue 项目里用
<div @click="submit">模拟按钮,测试时只用鼠标点,上线后视障用户完全无法提交表单
<main> 不是可选装饰,而是强制性地标
几乎所有主流屏幕阅读器(NVDA、VoiceOver、JAWS)都把 <main> 当作“页面主体内容”的唯一可信标识。它的使用有硬约束:
立即学习“前端免费学习笔记(深入)”;
- 一个页面只能有一个
<main>,且不能嵌套在<article>、<aside>、<header>等其他语义容器内 - 没写
<main>?屏幕阅读器会退而求其次找role="main",再找不到就从第一个<h1>开始当主体——极易误判(比如把页眉里的<h1>当正文开头) - 实测数据:含正确
<main>的页面,在 VoiceOver 中按M键直达主体的准确率是 100%;缺失时,用户平均需手动下拉 7–12 次才能定位到正文起始
最常被忽略的一点:<main> 必须包裹真正对用户有价值的内容,而不是空占位或仅含加载动画。如果主体内容是异步渲染的,得等 DOM 插入后再确保 <main> 已就位——否则屏幕阅读器初始化时就读不到任何主体信息。



















