内联svg必须用和而非alt,且二者须为svg前两个子元素;等价于alt需简明,补充上下文;纯装饰svg仍需空并设aria-hidden="true";role="img"和aria-label冗余有害;viewbox必须合法以确保图形可见;动态生成svg须手动注入和。

内联SVG必须用和,不能用alt
因为<svg></svg>不是<img>,它没有alt属性;浏览器和读屏软件只识别<title></title>(必填)和<desc></desc>(建议填),且它们必须是<svg></svg>的**第一个和第二个子元素**,顺序错或位置偏移会导致播报失败。
常见错误现象:写了alt="搜索图标"但读屏完全不读——那是无效 HTML 属性,被忽略;或者把<title></title>放在<path></path>后面,部分读屏器跳过。
-
<title></title>相当于<img>的alt,必须简明、信息等价,比如<title>关闭弹窗</title>,别写“叉号图标” -
<desc></desc>补充上下文,比如操作后果或数据含义:<desc>点击后清空当前表单并返回首页</desc> - 如果 SVG 是纯装饰(如背景分隔线),仍需加
<title></title>,但内容可为<title></title>(空标签),且父容器应设aria-hidden="true"
role="img"和aria-label在内联SVG里是冗余甚至有害的
内联<svg></svg>本身已是语义化图像容器,加role="img"或aria-label不仅多余,还可能干扰读屏逻辑——尤其当<title></title>已存在时,部分读屏器会优先读aria-label而跳过真实描述。
实操建议:
- 删掉所有给
<svg></svg>加的role、aria-label、aria-labelledby - 确保
<svg></svg>没被包裹在<div role="img">这类冗余结构里 <li>如果 SVG 作为按钮使用(比如带<code>onclick),直接给<svg></svg>加tabindex="0"和role="button",再配<title></title>,不要混用aria-label - 导出 SVG 时保留合法
viewBox,例如viewBox="0 0 24 24",别让设计工具生成viewBox="0 0 -10 -10" - 避免用 CSS
transform: scale()替代viewBox缩放,这会让坐标系失真,读屏器定位不准 - 响应式场景下,用
width="1em"+height="1em"+viewBox组合,确保文字大小变化时图标同步缩放,读屏器仍能关联上下文
viewBox影响可访问性渲染,但和无关
viewBox本身不参与可访问性,但它决定图形是否能被正确缩放和定位。如果viewBox缺失或值非法(如viewBox="0 0 0 0"),SVG 可能渲染为空白或错位,导致读屏器虽读出<title></title>,但用户看不到对应图形——这是典型的“可访问但不可见”问题。
检查点:
动态生成的SVG必须手动注入和
JS 创建的<svg></svg>节点默认不含可访问性标签,innerHTML或createElementNS插入后,必须显式追加<title></title>和<desc></desc>——浏览器不会自动补全,也不会继承父级文本。
示例(安全写法):
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('viewBox', '0 0 24 24');
const title = document.createElementNS('http://www.w3.org/2000/svg', 'title');
title.textContent = '下载文件';
svg.appendChild(title);
const desc = document.createElementNS('http://www.w3.org/2000/svg', 'desc');
desc.textContent = 'PDF格式,大小约2.3MB';
svg.appendChild(desc);
// 再 append path 等图形元素
容易踩的坑:用svg.innerHTML = '<title>...</title>
<path ...>'</path>时,若字符串拼接漏掉<title></title>或顺序颠倒,可访问性就断了;更稳妥的做法是 DOM 操作分步注入。
复杂点在于:不同读屏器对<title></title>位置的容错度不一,iOS VoiceOver 比 NVDA 更严格——所以别依赖“差不多能读”,必须按规范写死顺序和层级。











