如何正确设置 SVG 和 img 元素的 alt 属性以通过无障碍校验

本文详解 `jsx-a11y/img-redundant-alt` 规则报错原因,指出“image”“photo”“picture”等冗余词不应出现在 alt 文本中,并提供符合 wcag 与屏幕阅读器最佳实践的修复方案。

在 React 项目中使用 ESLint 的 jsx-a11y 插件时,你可能会遇到如下警告:

Redundant alt attribute. Screen-readers already announce 'img' tags as an image. You don’t need to use the words 'image', 'photo,' or 'picture' (or any specified custom words) in the alt prop

该警告由 jsx-a11y/img-redundant-alt 规则触发(注意:当前主流插件为 eslint-plugin-jsx-a11y,已取代早期 react-a11y),其核心逻辑是:屏幕阅读器(如 NVDA、VoiceOver)在解析 元素时,会自动播报“图片”或“图像”语义,因此 alt 文本中再重复使用 image、photo、picture 等词属于语义冗余,既降低可读性,也违背无障碍设计原则。

✅ 正确写法:用描述性内容替代冗余词

❌ 错误示例(触发警告):

@@##@@
@@##@@

✅ 正确示例(清晰、简洁、有意义):

@@##@@
@@##@@
? 提示:alt 文本应传达图像的功能或信息价值,而非其媒体类型。例如按钮中的图标应说明操作(如 alt="Delete item"),装饰性图片应设为空字符串 alt=""(并确保无 role="img" 等干扰语义)。

⚠ 特别注意 SVG 的处理方式

上述规则仅适用于 标签。对于内联 svg>(如问题中所示),不应设置 alt 属性——SVG 本身不支持 alt,强行添加会被忽略或引发 HTML 验证错误。

✅ 正确的 SVG 无障碍写法(根据用途选择):

  • 纯装饰性 SVG:添加 aria-hidden="true"(如题干中的灯泡图标),无需任何文本替代;
  • 有语义的 SVG(如图标按钮)
  • 独立信息图 SVG:使用 + <desc> 组合,并确保父容器有适当语义(如 role="img" 仅在必要时):<pre class="brush:php;toolbar:false;"><svg role="img" aria-labelledby="chart-title chart-desc"> <title id="chart-title">Monthly user engagement Bar chart showing active users from Jan to Jun: 12K, 14K, 18K, 21K, 25K, 29K. {/* paths & bars */}

? 可选:自定义规则关键词(不推荐)

若团队确需保留某些词(如品牌术语 photo 作为专有名词),可在 .eslintrc.js 中调整规则配置:

module.exports = {
  rules: {
    'jsx-a11y/img-redundant-alt': ['error', { components: ['Image'], words: ['image', 'photo', 'picture', 'illustration'] }]
  }
};

但强烈建议优先优化文案本身——真正无障碍的 alt 是「看不见却能理解」的。

✅ 总结

  • alt 不是格式占位符,而是关键的信息通道;
  • 删除 image/photo/picture 等冗余前缀,聚焦内容本质;
  • 不用 alt,按语义选用 aria-hidden、aria-label、/
  • 所有修改后,务必用真实屏幕阅读器(如 VoiceOver + Safari 或 NVDA + Firefox)测试播报效果。

遵循以上实践,不仅能消除 ESLint 警告,更能切实提升应用对视障用户的可用性与包容性。