alt属性是HTML5强制必需属性,缺失将导致验证失败和可访问性问题;装饰图须用alt="",功能图需描述行为意图而非外观,动态渲染须防undefined值,SVG须用<title>+<desc>替代。

alt 属性不是“图片挂了才补的备用文字”,而是 <img> 标签的强制属性——不写就违反 HTML5 规范,W3C 验证器报错,eslint-plugin-jsx-a11y 拦截,Lighthouse 标记为严重可访问性问题。
装饰性图片必须用 alt="",不是删掉、不是空格、不是 alt="decorative"
分隔线、背景花边、纯排版留白图,不传递任何语义信息,辅助技术应完全跳过。写成 alt="装饰线条" 或 alt="图片" 会让屏幕阅读器念出无意义词,造成干扰;写成 alt=" "(带空格)会被读作“空白”;不写则触发验证失败,且部分读屏器可能朗读 src 文件名(如 header-bg-02.jpg)。
- ✅ 正确:
<img src="divider.png" alt=""> - ❌ 错误:
<img src="divider.png">(缺属性) - ❌ 错误:
<img src="divider.png" alt=" ">(空格 ≠ 空字符串) - ❌ 错误:
<img src="divider.png" alt="装饰">(冗余朗读)
功能性图片的 alt 要说明「点击后做什么」,不是「看起来像什么」
图标按钮、链接头像、搜索入口等,用户关心的是行为意图,不是视觉形态。描述图形本身(如“放大镜”“齿轮”)对操作毫无帮助。
- ✅ 正确:
<img src="search.svg" alt="搜索"> - ✅ 正确:
<img src="close.png" alt="关闭弹窗"> - ✅ 正确:
<img src="logo.png" alt="返回首页">(当它作为首页链接时) - ❌ 错误:
<img src="cart-icon.png" alt="购物车图标">(用户不知道点后动作) - ⚠️ 注意:若链接旁已有可见文字(如“我的订单”),且图标纯装饰,则用
alt="",避免重复朗读
动态渲染场景下,alt 容易因状态未就绪而变成 undefined 或空字符串
React/Vue/JSX 中直接绑定数据字段,一旦 data.desc 为空或未定义,就会渲染出 alt="undefined" 或 alt=""(但本应有内容),CMS 后台未填字段时 fallback 到文件名也是常见问题。
立即学习“前端免费学习笔记(深入)”;
- ❌ 危险写法:
<img src={url} alt={data.desc} />→ 渲染为alt="undefined" - ✅ 安全写法:
<img src={url} alt={data?.desc || "加载中的示意图"} /> - ✅ Vue 模板:
<img :src="item.img" :alt="item.description || '无描述图片'"> - ✅ CMS 策略:上传时强制填写「图片描述」字段,拒绝空提交;未填则 fallback 为
alt="",而非文件名
Yii2 的 Html::img() 必须把 alt 放进第二个参数($options 数组),不能塞进外层 Html::a()
常见错误是把 alt 当作链接的属性传给 Html::a(),结果 alt 出现在 <a> 标签上,对内部 <img> 完全无效——HTML 允许 <a> 有 alt,但语义错位,读屏器不会把它当作图片替代文本。
- ❌ 错误:
Html::a(Html::img($src), $url, ['alt' => 'app logo'])→alt在<a>上 - ✅ 正确:
Html::a(Html::img($src, ['alt' => 'app logo']), $url)→alt在<img>上 - ✅ 更清晰:
Html::img($src, ['alt' => 'app logo', 'class' => 'logo-img'])
最容易被忽略的是 SVG 内联图——<svg> 标签本身不支持 alt 属性,得用 <title> + <desc> 组合,并确保父容器有 role="img",否则读屏器直接跳过。这不是加个属性就能解决的事,得单独处理语义结构。



















