尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

网页图片的无障碍实战:alt 到底怎么写,屏幕阅读器里那些图是什么样的

网页图片的无障碍实战:alt 到底怎么写,屏幕阅读器里那些图是什么样的
📅 发布时间:2026/7/14 18:26:40

做前端第八年,我第一次认真戴上耳机、关掉屏幕、用 VoiceOver 从头到尾"听"完自己做的页面,是被一个客服工单逼的。有个视障用户投诉说我们商品列表页"根本没法用,每张图都念一串乱码"。我打开一看——好家伙,产品图的 alt 全是后端拼的文件名,alt="IMG_20240517_093412_v2_final_final.jpg"。屏幕阅读器一板一眼地把这串东西读了出来。那一刻我意识到,我过去写的无数个alt属性,基本都是应付 lint 规则用的,从没考虑过它真正被念出来是什么感受。

这篇就把我这两年趟出来的图片可访问性经验倒一倒。不讲大道理,全是能直接抄进项目的判断和代码。

先分清:这张图到底是干嘛的

所有关于 alt 的纠结,本质都是一个问题没想清楚——这张图在页面里承担的是"信息"还是"装饰"。这两类的处理方式是相反的,混了就出错。

信息性图片,指的是图片本身携带内容,去掉它信息就缺了一块。产品照片、图表、说明性截图、有文字的 banner,都算。这类必须写有意义的 alt。

装饰性图片,指的是它纯粹是视觉点缀,去掉它内容一点不少。分隔线、圆角背景纹理、纯氛围的配图、和旁边文字重复的图标,都算。这类必须显式声明为空,让屏幕阅读器直接跳过。

关键的坑在装饰这一侧。很多人以为装饰图不写 alt 就行了,错。看这段:

<!-- 灾难写法:屏幕阅读器会念出 URL 或文件名 --><imgsrc="/assets/divider-gold.png"><!-- 正确:空 alt,屏幕阅读器完全跳过 --><imgsrc="/assets/divider-gold.png"alt="">

<img>没有 alt 属性时,多数屏幕阅读器会退而去读src的文件名当替代文本,于是用户听到一串divider-gold-png。而alt=""(注意是空字符串,中间不能有空格)是一个明确信号:这张图无内容价值,别念。这俩差了十万八千里,我 review 代码现在第一件事就是抓没有 alt 属性的<img>。

如果你更想表达语义上"这是个装饰角色",也可以用role="presentation"或role="none",效果和空 alt 类似,都是把元素从无障碍树里剔掉:

<imgsrc="/bg-texture.png"alt=""role="presentation">

不过实测下来,alt=""兼容性最稳,能覆盖到就够了,role是锦上添花。

信息性图片的 alt,写"内容"不写"外观"

好,装饰的搞定了,难的是信息图 alt 怎么写。我总结的一条准则:替代文本要传达图片承载的信息和功能,而不是描述像素长什么样。

举个例子,同一张"红色感叹号图标 + 库存不足"的图:

<!-- 描述外观,没用 --><imgsrc="/icon-warning.svg"alt="红色三角形里有个感叹号"><!-- 传达信息,对了 --><imgsrc="/icon-warning.svg"alt="库存不足">

用户不需要知道那是三角形还是圆形、红色还是橙色——那是给视觉设计看的。他需要知道的是"库存不足"这件事。

再进阶一层,alt 要看上下文。同一张爱因斯坦的照片,放在人物传记页和放在"经典打印海报"电商页,alt 该完全不同。前者可能是"阿尔伯特·爱因斯坦晚年肖像",后者更该是"爱因斯坦吐舌头黑白海报,A2 尺寸",因为在购物场景里用户关心的是这个商品是什么。同一张图没有标准答案,脱离上下文谈 alt 都是耍流氓。

几条我常用的实操细节:

  • alt 别加"图片:“” 一张……的照片"这种前缀。屏幕阅读器碰到<img>本来就会先播报"图像",你再写"图片"就成了"图像 图片 XXX",啰嗦。
  • 如果图片是个链接或按钮里唯一的内容,alt 必须描述这个操作会去哪/做什么,而不是描述图长啥样。比如站标 logo 通常链到首页,写alt="返回首页"比alt="公司logo"有用得多。
  • 图里有文字的话,alt 一般要把关键文字抄进去,尤其是营销图上的价格、优惠信息。这些文字对视觉用户可见,对视障用户就凭空消失了。
  • 长度别失控。一句话讲清就行,通常别超过一行。真需要长描述的(复杂图表),用下面讲的aria-describedby。

复杂图表和信息图:一句 alt 装不下

数据可视化是重灾区。一张趋势折线图,你 alt 写"2024 年销售趋势图"等于没写——用户知道有张图,但图里说了啥一无所知。

处理思路有两层。第一层,alt 给个概括结论。第二层,用aria-describedby挂一段详细的文字替代,把图里的数据讲清楚。

<figure><imgsrc="/sales-2024.svg"alt="2024 年季度销售额呈上升趋势"aria-describedby="sales-desc"><figcaptionid="sales-desc">Q1 销售额 120 万元,Q2 增至 165 万元,Q3 达到 210 万元, Q4 冲到 280 万元。全年环比持续增长,Q4 增幅最大, 较 Q3 提升约 33%。</figcaption></figure>

这里我把详细描述放进了可见的<figcaption>,一举两得:视觉用户也能看到数据摘要,视障用户通过aria-describedby关联读到。aria-describedby的值是目标元素的 id,屏幕阅读器读完 alt 会接着读这段。

早年有个longdesc属性专门干这事,但它是外链一个描述页面的,浏览器支持烂、维护也烦,现在基本淘汰了。aria-describedby加可见 figcaption 是我现在的默认解法。如果你不想让描述在视觉上显示,可以放进一个视觉隐藏但屏幕阅读器可读的容器(下面有.sr-only的写法),但我更倾向让所有人都看到数据摘要,反正对谁都有好处。

信息图(infographic)同理,那种一大张塞满流程和数字的图,最好在旁边或下方提供等价的结构化文本/列表,别指望一个 alt 交代清楚。

SVG 图标的可访问性,比 img 麻烦

内联 SVG 现在满天飞,但它不是<img>,没有 alt 属性,处理方式单独一套。而且不同屏幕阅读器对 SVG 的支持参差不齐,这块坑最多。

先分场景。

纯装饰的 SVG 图标(旁边已经有文字标签的那种),直接aria-hidden="true"藏掉:

<button><svgaria-hidden="true"focusable="false"width="16"height="16"><usehref="#icon-cart"></use></svg>加入购物车</button>

aria-hidden="true"把 SVG 从无障碍树移除,用户只会听到按钮的文字"加入购物车"。那个focusable="false"是给老 IE/Edge 擦屁股的——某些旧版本里 SVG 会意外可聚焦,Tab 键会卡在上面,加上这个防患。现在能不能省?看你兼容目标,我一般还是留着,一个属性的事。

承载信息的 SVG(比如一个只有图标没有文字的图标按钮),必须补语义。两种主流写法:

<!-- 方式一:aria-label 直接给可访问名 --><buttonaria-label="搜索"><svgaria-hidden="true"focusable="false"><usehref="#icon-search"/></svg></button><!-- 方式二:SVG 内部用 title + role --><svgrole="img"aria-labelledby="search-title"width="20"height="20"><titleid="search-title">搜索</title><usehref="#icon-search"/></svg>

方式一是我用得最多的:图标 SVG 一律aria-hidden,把可访问名交给外层的button/a用aria-label提供。逻辑清晰,也不受 SVG 屏幕阅读器兼容性折腾。

方式二用 SVG 内部的<title>加role="img"加aria-labelledby。注意光有<title>不够可靠,Safari+VoiceOver 有时不认,所以要显式role="img"加aria-labelledby指向 title 的 id,把三件套配齐兼容性才稳。SVG 里还有个<desc>可以放更长的描述,用得少,复杂图形才需要。

顺便提一句<use href="#...">引用 symbol 的写法,图标本体的 symbol 定义里也别塞 title,容易和使用处的语义打架,语义统一在使用处给。

CSS 背景图:无障碍树里根本不存在

这个概念很多人没意识到:用background-image铺的图,屏幕阅读器完全感知不到,无障碍树里它不存在。

这既是坑也是特性。

如果你拿背景图去放装饰性内容——纹理、渐变、氛围图——那太好了,天生就被无障碍忽略,你啥也不用管,这正是我们想要的。

但如果你偷懒把信息性内容做成了背景图(我见过有人把"限时五折"的促销文字直接切成背景图铺上去),那视障用户就彻底丢失了这个信息,因为背景图没有任何替代文本机制。这种情况要么改回<img alt>,要么在那个元素上补 ARIA:

<divclass="hero-banner"role="img"aria-label="限时五折促销,仅剩 3 天"></div>

给背景图容器加role="img"加aria-label,相当于手动把它塞回无障碍树。但说实话这是补救,能用真<img>就用真的,语义天然、SEO 也友好。

真机实测:VoiceOver 和 NVDA 会打架

代码写得再漂亮,不上真机听一遍都是纸上谈兵。我踩过最多的亏就是"看起来 ARIA 都对,实际读出来不对"。几个实测经验:

macOS VoiceOver(Cmd+F5 开启,Ctrl+Option+右方向键逐项走):对 SVG<title>的支持时好时坏,尤其配 Safari。前面说的role="img"加aria-labelledby三件套就是为了绕它。VoiceOver 读<img>会先播"图像"再读 alt。

Windows NVDA(免费,配 Firefox 或 Chrome 测):整体对 ARIA 支持更规矩,但它和浏览器的组合会影响结果——NVDA+Firefox 和 NVDA+Chrome 对同一段aria-describedby的播报时机能不一样。所以我至少测 VoiceOver/Safari + NVDA/Firefox 两组。

一个特别容易翻车的点:aria-label和元素内的可见文字同时存在时,aria-label会覆盖掉可见文字,屏幕阅读器只念 aria-label。我见过有人给一个"加入购物车"按钮加了aria-label="购物车",结果视障用户听到的是"购物车",把动作词"加入"给吞了。所以按钮如果本身有文字,多半根本不需要 aria-label,别画蛇添足。

还有个免费的低成本自查手段:装个 axe DevTools 或用 Lighthouse 的 accessibility 审计跑一遍,能自动抓出缺 alt、对比度不足这类硬伤。但记住,自动化工具只能查约 30%-40% 的问题,"alt 写得对不对、有没有意义"这种它判断不了,最后还得靠人戴上耳机真听。

一段能到处用的视觉隐藏工具类

最后送个高频工具。有时你想给屏幕阅读器提供额外文字(比如图标按钮的说明),又不想视觉上显示,别用display:none或visibility:hidden——那俩会把内容从无障碍树也一起干掉,屏幕阅读器读不到。要用这个经典的.sr-only:

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
<ahref="/cart"><svgaria-hidden="true"><usehref="#icon-cart"/></svg><spanclass="sr-only">购物车,3 件商品</span></a>

它把元素缩到 1px 挤出视口外、裁剪掉,视觉上不可见,但仍留在无障碍树里,屏幕阅读器照读。这一个类能解决大半"想补语义又不想动视觉"的场景。

说点诚实的边界

写到这儿得泼点冷水。图片可访问性没有银弹,alt的"正确"高度依赖上下文和业务判断,很多时候没有唯一答案,只有更合适的答案——这活儿本质上是内容工作,不是纯技术活,指望某个规则或工具帮你自动生成好 alt,目前都不现实。自动生成的描述往往只描述像素、抓不住页面语境,还得人来兜底改。

另外我这套经验主要覆盖屏幕阅读器这一类用户,可访问性远不止于此——低视力放大、色盲对比度、键盘导航、认知障碍,每一块都是深水区,我也还在学。SVG 那部分的兼容性尤其是流沙,浏览器和读屏软件版本一变可能就有出入,别把我上面写的当成永久真理,上你自己的目标环境实测才算数。

真要开始改,我的建议是别追求一步到位。先跑个 axe 把没有 alt 的图全揪出来堵上(这是最低标准,也是收益最高的一步),再逐步区分装饰与信息、给关键图表补文字替代。哪怕只做到第一步,对那些戴着耳机"听"你页面的用户来说,已经是天壤之别了。图片是网页里最容易被无障碍遗忘的角落,但它其实是最好补的一块——很多时候,就差一个认真写的alt。

相关新闻

  • 人脸识别:从DeepID到FaceNet的“度量”艺术
  • 如何用Jboot实现分布式事务?Seata与ShardingSphere集成实战
  • 免费开源的PDF差异检测工具:5分钟快速上手diff-pdf

最新新闻

  • 计算机毕业设计之基于SSM框架的流浪狗收容管理系统
  • Linux系统xz命令进阶实战:从基础压缩到高效归档与性能调优
  • Ice:Mac菜单栏管理终极指南,3步打造高效工作空间
  • C++17多态内存资源(PMR)实战:原理、性能优化与工程应用
  • 2026年7月亲身探访扬州亨得利官方名表服务中心|最新热线及维修地址 - 亨得利官方
  • Win系统软件闪屏/Edge闪屏/Office闪屏 - 从硬件加速到驱动残留的深度排查与根治

日新闻

  • AWS SSM安全运维实践:零公网暴露的合规远程开发方案
  • Tableau 2024.1 图表选择指南:5种业务场景与最佳图表类型匹配
  • dsPIC33FJ与CMT-8540S-SMT在嵌入式音频处理中的高效应用

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号