Skip to main content

SVG 访问性

· 3 min read

按钮必须有可访问名称(对屏幕阅读器来说有“名字”),这个名字可以来自按钮的可见文本、aria-label、或 aria-labelledby;如果 SVG 只是装饰,给它 aria-hidden="true"(同时 focusable="false");如果 SVG 本身承载语义(例如显示状态),确保它参与名称或用 ARIA 状态描述按钮(例如 aria-pressed / aria-expanded)。


场景 A:图标 + 可见文本

按钮内部有文本,屏幕阅读器会从文本获得名称。这里把 SVG 标记为装饰。

<button type="button" class="btn">
<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="...">
{/* svg shapes */}
</svg>
<span>保存</span>
</button>
  • aria-hidden="true":屏读器忽略 svg(因为文本已经提供名称)。
  • focusable="false":防止旧版本 IE/Edge 将 svg 单独聚焦。

场景 B:图标按钮(仅图标,无可见文本)

必须为按钮提供一个可访问名称(通常用 aria-label)。这是最常见的图标按钮形式(如“关闭”、“搜索”图标)。

// 推荐:使用 aria-label
<button type="button" aria-label="关闭" class="icon-btn">
<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="...">
{/* svg shapes */}
</svg>
</button>

场景 C:用 SVG 的 <title> 作为可访问名称

注意:<title> 在不同屏读器/浏览器里的支持不完全一致。最可靠的方式还是把名字放在 aria-label 或把可见文本放在 DOM 中。如果你确实想复用 svg 的 <title>,可以让按钮通过 aria-labelledby 指向 <title> 的 id:

<button type="button" aria-labelledby="closeTitle">
<svg width="16" height="16" viewBox="..." focusable="false" role="img" aria-hidden="false">
<title id="closeTitle">关闭</title>
{/* svg shapes */}
</svg>
</button>

但要小心兼容性 —— 通常建议直接使用 aria-label(更稳妥)。


场景 D:可切换/开关按钮(例如喜欢/收藏)

如果按钮表示开/关状态,使用 ARIA 状态属性(aria-pressedaria-checked、或 aria-expanded 等),并确保屏读器能读到当前状态。

const [pressed, setPressed] = useState(false);

<button type="button"
aria-pressed={pressed}
aria-label="收藏此项"
class="icon-btn">
<svg width="16" height="16" viewBox="..." focusable="false" aria-hidden="true">
<!-- heart icon -->
</svg>
</button>

给出 aria-pressed(或其他合适的 ARIA 属性)并更新可访问名称以反映当前状态。


场景 E:用 CSS 背景图作为图标

如果图标仅装饰且不需要交互或描述,使用 CSS 背景图是个简单办法(屏读器默认不可见):

<button type="button" class="btn-with-bg" aria-label="关闭"></button>

/* css */
.btn-with-bg {
width: 40px;
height: 40px;
background-image: url('/icons/close.svg');
background-size: contain;
background-repeat: no-repeat;
}

但注意:如果图标承载信息或是主要视觉内容,优先使用 inline <svg><img alt="">