用div写导航会被屏幕阅读器忽略,因其无语义,无法识别为导航区块;应改用,菜单项须用或role="link",当前页加aria-current="page",面包屑用,标题需严格嵌套,商品列表优先用+,骨架屏也需保持语义一致。

为什么用写导航会被屏幕阅读器忽略
因为 div 没有语义,读屏软件无法识别它是导航区块。它只当普通容器处理,不会暴露“这是导航”这一意图,用户无法通过快捷键(如 JAWS 的 N 键)跳转到导航区。
实操建议:
- 把
<div class="nav"> 改成 <code><nav aria-label="主导航"></nav>,aria-label 是给读屏软件的明确说明
- 菜单项必须用
<a></a> 或带 role="link" 的元素,不能只靠 click 事件模拟链接
- 当前页链接加
aria-current="page",否则读屏用户不知道自己在哪
- 面包屑必须用
<ol></ol> 而非 <ul></ul>,顺序语义不可替代
标题层级错乱会导致什么实际问题
不是“看起来不太对”,而是直接破坏辅助技术的导航逻辑:大纲生成错误、跳转锚点失效、语音指令(如“跳到二级标题”)找不到目标。
常见错误现象:<h3></h3> 直接跟在 <h1></h1> 后面,中间缺 <h2></h2>;或用 <h2></h2> 当样式标题,实际内容逻辑上只是强调文字。
实操建议:
- 每个页面只有一个
<h1></h1>,通常是主标题或品牌名
-
<main></main> 内部的标题必须连续嵌套:<h1></h1> → <h2></h2> → <h3></h3>,不跳级也不回退
- 用浏览器开发者工具的「Accessibility」面板实时检查大纲树,比肉眼更可靠
- 组件库输出的标题(如 Vue 的
<title></title>)要确认渲染后是否为真实 <h2></h2> 标签,而非包裹在 <div> 里
<h3>商品列表用</h3>
<table>还是<ul>更可访问
<p>两者都可行,但语义和交互预期完全不同:<code><table> 表达二维关系(行列交叉含义),<code><ul></ul> 表达线性序列。电商商品列表本质是“一组并列商品”,不是表格数据,强行用 <table> 反而误导读屏软件进入“表格导航模式”,增加操作成本。
<p>实操建议:</p>
<ul><li>优先用 <code><ul role="list"></ul> + <li role="listitem">,显式声明语义(尤其当框架自动输出 <div> 时)
<li>每个商品卡片用 <code><article></article> 包裹,它自带独立语义,读屏软件可识别为“可单独引用的内容单元”
- 价格、库存等关键信息别藏在伪元素或
title 属性里——读屏默认不读 title,伪元素内容不可聚焦也不可被脚本获取
- 筛选控件必须关联
<label></label> 或用 aria-labelledby,否则键盘用户无法知道下拉框用途
骨架屏内联HTML时如何保留可访问性
骨架屏不是视觉占位符,它也是 DOM 的一部分。如果内联的骨架结构没语义,加载真实内容后,读屏软件会感知两次结构变化(先读无意义骨架,再读真实内容),造成混乱甚至跳过关键信息。
实操建议:
- 骨架节点也用真实语义标签:
<nav></nav> 套骨架导航,<article></article> 套骨架商品,别全用 <div class="skeleton">
<li>文字占位用 <code><span class="skeleton-text"></span>,而非伪元素生成内容——后者对读屏不可见,且无法被焦点管理
- 图片占位区域保留
<img> 标签,设 src="data:image/svg+xml,%3Csvg..." 和 alt="",避免读屏误报“缺失图片”
- 首屏骨架内联时,确保
和 <meta charset="UTF-8"> 已存在,否则骨架文本可能乱码或读音错误
复杂点在于:可访问性不是加几个属性就完事,它要求骨架、真实内容、JS 交互三者语义一致。最容易被忽略的是骨架阶段的 aria-live 控制——真实内容替换骨架时,若没正确设置 aria-live="polite" 或 aria-busy="true",读屏用户会听到突兀的、无上下文的信息流。
因为 div 没有语义,读屏软件无法识别它是导航区块。它只当普通容器处理,不会暴露“这是导航”这一意图,用户无法通过快捷键(如 JAWS 的 N 键)跳转到导航区。
实操建议:
- 把
<div class="nav"> 改成 <code><nav aria-label="主导航"></nav>,aria-label是给读屏软件的明确说明 - 菜单项必须用
<a></a>或带role="link"的元素,不能只靠click事件模拟链接 - 当前页链接加
aria-current="page",否则读屏用户不知道自己在哪 - 面包屑必须用
<ol></ol>而非<ul></ul>,顺序语义不可替代 - 每个页面只有一个
<h1></h1>,通常是主标题或品牌名 -
<main></main>内部的标题必须连续嵌套:<h1></h1>→<h2></h2>→<h3></h3>,不跳级也不回退 - 用浏览器开发者工具的「Accessibility」面板实时检查大纲树,比肉眼更可靠
- 组件库输出的标题(如 Vue 的
<title></title>)要确认渲染后是否为真实<h2></h2>标签,而非包裹在<div> 里 <h3>商品列表用</h3> <table>还是<ul>更可访问 <p>两者都可行,但语义和交互预期完全不同:<code><table> 表达二维关系(行列交叉含义),<code><ul></ul>表达线性序列。电商商品列表本质是“一组并列商品”,不是表格数据,强行用<table> 反而误导读屏软件进入“表格导航模式”,增加操作成本。 <p>实操建议:</p> <ul><li>优先用 <code><ul role="list"></ul>+<li role="listitem">,显式声明语义(尤其当框架自动输出<div> 时) <li>每个商品卡片用 <code><article></article>包裹,它自带独立语义,读屏软件可识别为“可单独引用的内容单元” - 价格、库存等关键信息别藏在伪元素或
title属性里——读屏默认不读title,伪元素内容不可聚焦也不可被脚本获取 - 筛选控件必须关联
<label></label>或用aria-labelledby,否则键盘用户无法知道下拉框用途 - 骨架节点也用真实语义标签:
<nav></nav>套骨架导航,<article></article>套骨架商品,别全用<div class="skeleton"> <li>文字占位用 <code><span class="skeleton-text"></span>,而非伪元素生成内容——后者对读屏不可见,且无法被焦点管理 - 图片占位区域保留
<img>标签,设src="data:image/svg+xml,%3Csvg..."和alt="",避免读屏误报“缺失图片” - 首屏骨架内联时,确保
和<meta charset="UTF-8">已存在,否则骨架文本可能乱码或读音错误
复杂点在于:可访问性不是加几个属性就完事,它要求骨架、真实内容、JS 交互三者语义一致。最容易被忽略的是骨架阶段的
标题层级错乱会导致什么实际问题
不是“看起来不太对”,而是直接破坏辅助技术的导航逻辑:大纲生成错误、跳转锚点失效、语音指令(如“跳到二级标题”)找不到目标。
常见错误现象:<h3></h3> 直接跟在 <h1></h1> 后面,中间缺 <h2></h2>;或用 <h2></h2> 当样式标题,实际内容逻辑上只是强调文字。
实操建议:
骨架屏内联HTML时如何保留可访问性
骨架屏不是视觉占位符,它也是 DOM 的一部分。如果内联的骨架结构没语义,加载真实内容后,读屏软件会感知两次结构变化(先读无意义骨架,再读真实内容),造成混乱甚至跳过关键信息。
实操建议:
aria-live 控制——真实内容替换骨架时,若没正确设置 aria-live="polite" 或 aria-busy="true",读屏用户会听到突兀的、无上下文的信息流。











