自定义按钮组件的屏幕阅读器读的是图标而不是文本怎么办?
我在用Vue写一个带图标的按钮组件,结构是这样:<button><span>删除</span><svg>...</svg></button>。但屏幕阅读器总读出”图标 图标”而不是”删除”文本,试过加aria-label="删除"但没效果,这是为什么啊?
后来我把按钮改成纯文字测试,发现能正常读取。但需要保留图标时,该怎么让屏幕阅读器忽略SVG只读文字?是不是应该用aria-hidden?或者我的组件结构有问题?
现在组件代码大概是这样:
<button :aria-label="text">
<span>{{ text }}</span>
<svg class="icon" aria-hidden="true">...</svg>
</button>
但还是不行,有没有更好的实现方式?
首先说解决方案,建议把组件结构调整一下,像这样:
这里的关键点有几个:第一是给SVG同时加上aria-hidden="true"和focusable="false",后者是为了防止IE浏览器把SVG识别为可聚焦元素。第二是用一个专门的类名比如sr-only或者visually-hidden来隐藏文字视觉显示,但让屏幕阅读器可以读到。
这个类的样式可以这样写:
另外说下为什么你的代码可能没生效。有时候即使加了aria-hidden,但如果SVG内部还有其他可访问性属性,比如title或desc,也会影响屏幕阅读器的解读。所以最好确保SVG内部是干净的,只保留图形信息。
最后提醒一下,记得测试不同屏幕阅读器的兼容性,比如NVDA、JAWS和VoiceOver,因为它们的解析方式会有些差异。希望这些建议能帮你解决问题!
1. 首先是
aria-label的使用。这个属性确实可以给按钮定义一个可访问的名称,但它的优先级会被按钮里的可见内容覆盖。所以如果<span>里的文本已经存在,aria-label就不会生效。直接去掉它或者把aria-label放在备用方案里。2. 对于
<svg>,加aria-hidden="true"是对的,这样可以让屏幕阅读器忽略图标。不过要确保 SVG 本身没有多余的可访问性属性(比如role或者嵌套的title标签),这些可能会干扰。3. 推荐的结构是这样的:
4. 如果你想更保险一点,可以用
aria-labelledby来明确指定屏幕阅读器应该读哪个元素的内容。例如:最后提醒一下,写这种组件时一定要注意防止注入,尤其是当
text是动态传入的时候,确保内容被正确转义或验证过。希望这个方案能解决你的问题!