首页
/ Front-End-Checklist 规则实战:为图片提供有意义的 alt 文本(alt-text 规则全解)

Front-End-Checklist 规则实战:为图片提供有意义的 alt 文本(alt-text 规则全解)

2026-09-04 09:09:07作者:魏侃纯Zoe

本文基于 Front-End-Checklist 仓库中的 alt-text 规则参考文档,系统讲解图片可访问性的核心机制:为什么每个 <img> 都必须有 alt 属性、不同角色(信息性、装饰性、链接、纯文字、复杂图表)的图片应如何取值、如何在 React/Next.js 中落地,以及如何用 axe、Lighthouse 和屏幕阅读器完成验证。读完后,你既能手动修复图片 alt 问题,也能理解该规则在仓库中从 MDX 源文件到 Agent 可安装 skill 的完整生成链路。

规则定位与元信息

alt 属性是图片可访问性的首要机制。规则文档给出的定位是:每个 <img> 都必须有 alt 属性,其取值取决于图片在页面中所扮演的角色(见 rules 正文)。

该规则的元信息(定义在源 MDX 的 frontmatter 中,见 alt-text.mdx):

字段 含义
priority critical 最高优先级,属于必须修复的问题
difficulty beginner 入门难度,改动通常是加一个属性
estimatedTime 15 min 单个页面的典型修复耗时
categories images / accessibility 归类于图片类规则,子类别为可访问性

为什么是 critical 优先级? 文档给出了三层依据:

  1. 规模:全球约有 22 亿人存在视力障碍,屏幕阅读器会逐字朗读 alt 属性——没有有意义的 alt,视障用户对图片内容一无所知;
  2. 合规:缺失 alt 直接违反 WCAG 2.1 Success Criterion 1.1.1(非文本内容),这是 Level A(最低级)要求,合规基线的第一道门槛;
  3. SEO:搜索引擎同样依赖 alt 文本来索引图片内容。

核心原则:alt 描述"图片传达了什么",而不是"图片长什么样"

文档用一个营收图表的例子完整展示了四种典型错误与正确写法:

<!-- ❌ Bad: Missing alt -->
<img src="revenue-chart.png">

<!-- ❌ Bad: Filename as alt -->
<img src="revenue-chart.png" alt="revenue-chart.png">

<!-- ❌ Bad: Generic alt -->
<img src="revenue-chart.png" alt="chart">

<!-- ✅ Good: Describes what the image conveys -->
<img
  src="revenue-chart.png"
  alt="Bar chart showing Q3 2024 revenue increased 40% year-over-year, reaching $2.4M"
>

四个反例覆盖了真实代码库中最常见的失误模式:完全缺失、文件名当 alt、泛化 altalt="image"alt="photo")。规则文档明确指出,糟糕的 alt(如 alt="image")与没有 alt 没有本质区别——它占用了属性位却不传递任何信息。判断某张图该取什么值时,文档建议参照 W3C 官方的 alt 决策树(该决策树也列在源 MDX 的 resources 字段 中)。

四类特殊场景的取值策略

规则文档把图片按角色分为四类特殊场景,每类有独立的取值策略,这也是修复工作的核心决策树。

装饰性图片:alt="" 显式隐藏

纯粹用于视觉装饰的图片不承载信息,应让辅助技术完全跳过。关键点在于 alt=""(空字符串)与省略 alt 行为完全不同:

<!-- ❌ Bad: No alt attribute—screen reader may announce the filename -->
<img src="decorative-swirl.png">

<!-- ✅ Good: Empty alt hides image from screen readers -->
<img src="decorative-swirl.png" alt="">

<!-- ✅ Good: Or use CSS background images for decoration -->
<div class="decorative-swirl" aria-hidden="true"></div>

省略 alt 时,部分屏幕阅读器会朗读文件名(如 "decorative-swirl.png"),反而制造噪声。文档还给出第三条路线:纯装饰效果直接用 CSS 背景图 + aria-hidden="true" 容器。仓库中生成的全局审计 skill 也印证了这一立场——generate-skills.ts 中明确要求审计时"不要把 alt="" 默认当问题",把 <img ... alt="" aria-hidden="true"> 视为零问题安全模式(Zero-issue pattern)。

作为链接的图片:alt 描述链接目的地

<img> 被包在 <a> 里时,图片承担的是"链接"角色,屏幕阅读器朗读的是 alt + "链接",因此 alt 应描述跳转目标而非视觉外观:

<!-- ❌ Bad: Describes appearance, not destination -->
<a href="https://twitter.com/example">
  <img src="twitter-logo.svg" alt="Blue bird logo">
</a>

<!-- ✅ Good: Describes the link destination -->
<a href="https://twitter.com/example">
  <img src="twitter-logo.svg" alt="Follow us on Twitter">
</a>

文字图片:alt 逐字复刻图中文字

图片本身承载文字(logo、横幅、截图)时,alt 应逐字(verbatim)复刻其中的文字,让屏幕阅读器用户获得与视觉用户一致的内容:

<!-- ✅ Good: Alt reproduces the text shown in the image -->
<img src="sale-banner.png" alt="Summer Sale — 50% off all items">

<!-- ✅ Good: Logo with company name -->
<img src="logo.svg" alt="Acme Corp">

复杂图片(图表、示意图):短 alt + 长描述

复杂视觉内容无法在一行 alt 内说清,策略是"简短 alt + 对所有用户可见的长描述"。文档给出的实现是用 aria-describedby 关联一个可见的 figcaption

<!-- Using aria-describedby to link to a visible description -->
<figure>
  <img
    src="org-chart.png"
    alt="Company organisational chart"
    aria-describedby="org-chart-desc"
  >
  <figcaption id="org-chart-desc">
    The chart shows three departments reporting to the CEO: Engineering (12 staff),
    Marketing (8 staff), and Operations (5 staff).
  </figcaption>
</figure>

这种"可见描述 + aria-describedby"的组合是刻意设计:长描述放在 <figcaption> 里让所有用户都能读到(而非仅屏幕阅读器),aria-describedby 则保证朗读顺序自然衔接。这也解释了源 MDX 中 relatedRules 字段 为何把 figure-figcaption 列为第一条关联规则——两条规则在复杂图片场景下天然成对出现。

框架落地:React 与 Next.js 示例

规则文档提供了两套框架级写法,核心思想是把"装饰性 → 空字符串"的决策固化进组件 API,从类型层面杜绝忘记传 alt。

React 组件封装(装饰性走 decorative 布尔开关):

interface ImageProps {
  src: string
  alt: string
  decorative?: boolean
}

function AccessibleImage({ src, alt, decorative = false }: ImageProps) {
  return (
    <img
      src={src}
      // Decorative images use empty string; informative images use descriptive text
      alt={decorative ? '' : alt}
    />
  )
}

// Usage
<AccessibleImage src="hero.jpg" alt="Team members collaborating in a modern office" />
<AccessibleImage src="divider.png" decorative />

Next.js 版本(next/image 强制要求 alt,装饰图传 ""):

import Image from 'next/image'

// Next.js Image requires alt; use "" for decorative
function HeroBanner() {
  return (
    <>
      {/* Informative */}
      <Image
        src="/hero.jpg"
        alt="Product team celebrating a successful launch"
        width={1200}
        height={600}
        priority
      />

      {/* Decorative */}
      <Image
        src="/wave-divider.svg"
        alt=""
        width={1200}
        height={60}
        aria-hidden="true"
      />
    </>
  )
}

注意装饰图的 alt=""aria-hidden="true" 同时出现——前者处理 <img> 语义,后者进一步抑制辅助树,两者并不冲突而是双保险(对应文档 Verification 一节中"SVG 图标 + 相邻文字标签时用 aria-hidden"的原则在位图场景的延伸)。

Agent 视角:Check / Fix / Explain 三步提示

除了给人读的正文,该规则在 skills/alt-text/SKILL.md 中还以"Agent 可执行的指令"形式存在,包含四段机器可读提示。这是本仓库"规则同时服务人类和 AI Agent"设计的一部分。

Check(检查步骤)——扫描代码库中所有 <img> 元素,逐项验证:

  1. 每个 <img> 都有 alt 属性(缺失即错误);
  2. 装饰性图片使用 alt=""
  3. 信息性图片的描述传达图片含义,而非仅文件名;
  4. 链接图片描述目的地;
  5. 文字图片在 alt 中复刻文字。

命中以下任一项即应标记:无 altalt 与文件名相同(如 alt="photo1.jpg")、泛化值(alt="image" / alt="photo")。

Fix(修复步骤)——对每张问题图片按角色执行:信息性图片描述其传达内容(alt="Bar chart showing 40% increase in sales Q3 2024" 而非 alt="chart");装饰性图片补 alt="";链接图片描述目的地;文字图片逐字复制图中文字;复杂图片用短 alt + aria-describedby 或可见说明。

Explain(解释话术)——面向用户解释 WCAG 2.1 SC 1.1.1 时强调:屏幕阅读器朗读 alt;alt="image" 这类差值等于没有;装饰图必须显式 alt="",因为省略 alt 会导致部分屏幕阅读器朗读文件名。

这四段提示并非手工维护——它们正是源 MDX frontmatter 中 prompts.check / prompts.fix / prompts.explain / prompts.codeReview 字段(见 alt-text.mdx frontmatter)逐字落地的结果。

验证方法:自动化工具 + 手动检查

规则文档将验证拆为两条线。

自动化检查

  • axe DevTools / WAVE:两者都会标记"缺失 alt"以及"非装饰性图片使用了空 alt"——注意它们能区分装饰图(空 alt 合法)与信息图(空 alt 违规);
  • Lighthouse 可访问性审计Images do not have alternate text 是计分项(scored item),意味着它会直接影响总分。

这三个工具的名称与链接同时登记在源 MDX 的 tools 字段 中,说明验证手段是规则定义的一部分,而非事后补充。

手动检查

  • 启用屏幕阅读器(VoiceOver / NVDA / JAWS),用 G 键在图片间导航,逐一确认朗读内容;
  • 在 Network 面板中任选一个图片 URL,回到 DOM 核对对应 <img> 是否有有意义的 alt
  • CAPTCHA 图片:alt 应描述目的而非字符(如 alt="CAPTCHA: type the characters shown"),并按 WCAG 1.1.1 提供语音替代方案;
  • 带相邻文字标签的 SVG 图标:图标的含义已被可见文字表达时,对 SVG 使用 aria-hidden="true" 而不是 alt。

最后两条是规则文档中最容易被遗漏的边界案例:CAPTCHA 的"字符"本身不应被朗读(也不应被 alt 预先剧透),而"图标 + 文字"组合属于语义冗余,此时 alt 反而是多余的。

仓库中的生成链路:从 MDX 到 skills/alt-text

理解 skills/alt-text/references/rule.md 从何而来,能帮你判断该文档的可信边界:它不是手写副本,而是生成产物。

  1. 唯一事实源packages/content/rules/en/images/alt-text.mdx——frontmatter 承载元数据(priority、tools、resources、prompts、tldr),正文承载上述全部技术内容;
  2. 生成脚本 scripts/generate/generate-skills.ts 读取该 MDX:buildSkillMd()(约 L88-L160)把 tldr 展开为 Quick Reference、把 prompts 四字段展开为 Check/Fix/Explain/Code Review 小节,产出 SKILL.mdbuildReferencesMd()(约 L165-L186)把正文中的 MDX 组件(<Tip><CodeTabs><Tab> 等 JSX)经 stripMdxToMarkdown() 剥离为纯 Markdown,产出 references/rule.md——这解释了你在 rule.md 中看到的 Framework Examples 章节为何有连续空行(Tab 组件被剥离、代码块保留);
  3. 触发方式:根 package.jsongenerate:skills 脚本运行 tsx scripts/generate/generate-skills.ts,支持全量生成和传入具体 .mdx 路径的增量模式,后者被 lefthook 在规则 MDX 变更时自动调用(见 scripts/README.md);
  4. 运行时消费:Web 端通过 apps/web/lib/rule-content.tsgetRuleRawContent 直接从磁盘读取 MDX 正文并剥离 frontmatter(带 unstable_cache 缓存),供规则详情页与 /api/fix-suggestion?slug=alt-text 这类接口使用。

由于 references/rule.md 由 MDX 正文转换而来,若发现两者表述差异,以 MDX 源文件为准,并按仓库文档(见 AGENTS.md)通过 pnpm generate:skills 重新生成。

关联规则与标准依据

源 MDX 的 relatedRules 字段声明了三条需要协同审查的规则:

  • figure-figcaption:可见说明与 alt 在复杂图片上互补;
  • error-images:图片加载失败的降级图同样需要 alt 才能保持可访问;
  • dimensions:与 alt 一样作用于图片,常在同一次审查中一并处理。

文档 "Standards" 一节还要求:在认定规则满足之前,实现必须对照 MDN 的 Responsive images 与 web.dev 的 Image performance 两份权威参考核验——这两个 source 亦登记在 frontmatter sources 字段 中。

适用前提:本文所有结论以当前仓库的 alt-text 规则版本为准(priority=critical,Level A 合规项);WCAG 2.1 SC 1.1.1 的判定语义(如"等效文本必须随图片缩放同步可用")以 W3C 原文为最终依据,规则文档未覆盖的边界(如 SVG 内部 <title> 与 alt 的取舍)建议在具体项目中单独核实。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384