Your alt text passes automated checks. That doesn’t mean it’s any good.

2026-08-25 36 预计阅读时间: 1 分钟
来源: github.blog AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:12 分钟

{"title_zh":"通过自动化检查之后,Alt 文本仍然可能不合格","body_zh":"# 通过自动化检查之后,Alt 文本仍然可能不合格\n\n自动化工具能发现缺少 alt 属性、属性为空或写法不符合规则的问题,但“通过检查”只说明 HTML 结构满足了某些条件,并不代表屏幕阅读器用户获得了有用的信息。真正困难的地方在于:这张图片对当前页面任务意味着什么?\n\nGitHub Accessibility Scanner 的相关插件正是为了解决这层落差:把 Alt 文本从一个静态字段,提升为需要结合图片内容、页面上下文和用户任务来判断的内容。\n\n## alt 存在,不等于信息完整\n\n下面这些写法可能都能通过基础自动化检查:\n\nhtml\n<img src=\"chart.png\" alt=\"chart\">\n<img src=\"team.jpg\" alt=\"team photo\">\n<img src=\"warning.svg\" alt=\"warning icon\">\n\n\n它们的问题并不完全相同:\n\n- chart 没有说明图表展示了什么,也没有提供关键趋势或结论。\n- team photo 没有告诉用户照片中的人、场景或它在页面中的作用。\n- warning icon 可能只是装饰,也可能传达“操作失败”这一重要状态;两种情况下的处理方式不同。\n\n更有用的判断是把图片分成几类:\n\n1. 信息图片:Alt 文本应传达用户完成任务所需的内容。\n2. 功能图片:如果图片是链接或按钮,Alt 文本应描述操作结果,而不是图片外观。\n3. 装饰图片:使用空 Alt 文本 alt=\"\",让辅助技术跳过它。\n4. 复杂图表:Alt 文本提供摘要,旁边再提供可访问的详细数据或说明。\n\n这也是自动化工具的边界:它擅长检查“有没有字段”,却很难独立判断“字段是否回答了用户真正的问题”。\n\n## 让规则检查和人工判断配合起来\n\n可以把 Alt 文本审查拆成两道门。第一道门由 CI 或编辑器插件完成,快速拦截结构性错误;第二道门检查内容是否符合上下文。\n\n下面是一个可以改造成项目脚本的最小示例。它不会试图假装理解所有图片,而是先拦截几种高风险的通用文本,再把复杂案例交给人工复核。运行前请把 pages 改成项目实际的 HTML 文件列表。\n\npython\nfrom pathlib import Path\nimport re\nimport sys\n\nGENERIC_ALT = {\n \"image\", \"photo\", \"picture\", \"graphic\",\n \"image of\", \"photo of\", \"icon\",\n}\n\nIMG_RE = re.compile(r\"<img\\b[^>]*>\", re.IGNORECASE)\nALT_RE = re.compile(r\"\\balt\\s*=\\s*([\\\"'])(.*?)\\1\", re.IGNORECASE | re.DOTALL)\n\ndef review(path: Path) -> list[str]:\n html = path.read_text(encoding=\"utf-8\")\n problems = []\n\n for number, tag in enumerate(IMG_RE.findall(html), start=1):\n match = ALT_RE.search(tag)\n if match is None:\n problems.append(f\"{path}: image {number} is missing alt\")\n continue\n\n alt = \" \\".join(match.group(2).split()).strip()\n if alt.lower() in GENERIC_ALT:\n problems.append(f\"{path}: image {number} has generic alt: {alt!r}\")\n elif len(alt) > 160:\n problems.append(f\"{path}: image {number} alt is too long; consider nearby details\")\n\n return problems\n\npaths = [Path(name) for name in sys.argv[1:]]\nerrors = [problem for path in paths for problem in review(path)]\nfor error in errors:\n print(error)\n\nsys.exit(1 if errors else 0)\n\n\n这个脚本只是一个起点。实际项目中可以继续加入以下规则:\n\n- 将纯装饰图片列入允许的例外,并要求明确使用 alt=\"\"。\n- 对链接或按钮中的图片,检查可访问名称是否表达动作。\n- 对图表要求存在数据表、摘要或相邻的文字说明。\n- 把人工复核结果记录在 issue 或代码审查中,而不是简单地关闭告警。\n\n## 为什么需要专门的插件\n\n一个插件的价值不只是增加告警数量,而是把“内容质量”带入开发者已有的工作流。理想的检查结果应指出具体元素、说明风险,并提供足够上下文,让开发者知道该修改 Alt 文本、补充邻近说明,还是把图片标记为装饰。\n\n例如,对一张展示发布延迟变化的图表,下面两种文本的作用差别很大:\n\nhtml\n<!-- 结构上存在 alt,但信息不足 -->\n<img src=\"latency.png\" alt=\"latency chart\">\n\n<!-- 提供摘要,详细数据仍应以可访问文本或表格呈现 -->\n<img\n src=\"latency.png\"\n alt=\"从一月到三月,发布延迟由 18 分钟降至 7 分钟,二月短暂升至 12 分钟。\"\n>\n\n\n第二个版本也不一定适合所有场景。如果图表支持决策,最好同时提供数据表或文字版结论;如果图片只是文章装饰,则应该使用空 Alt 文本。插件可以帮助团队发现需要思考的地方,但不能替代对页面目的的理解。\n\n## 一份可落地的审查清单\n\n提交页面或组件前,可以逐项确认:\n\n- 图片是否有明确的语义角色:信息、功能、装饰,还是复杂内容?\n- 信息图片的 Alt 文本是否传达了任务相关内容,而非只描述“这是一张图片”?\n- 功能图片是否说明点击后会发生什么?\n- 装饰图片是否使用了空 Alt 文本,并避免把无意义内容读给用户?\n- 图表、流程图和截图是否提供了足够的替代信息?\n- 文本是否依赖颜色、位置或视觉细节才能理解?\n- 自动化检查通过后,是否仍有一轮基于页面上下文的人工抽查?\n\n把自动化扫描当作最低门槛,而不是质量证明。Alt 文本真正合格的标准不是“工具没有报错”,而是使用屏幕阅读器的人能否获得与其他用户相近、并且足以完成当前任务的信息。","title_en":"Passing Automated Checks Does Not Make Alt Text Good","body_en":"# Passing Automated Checks Does Not Make Alt Text Good\n\nAutomated accessibility checks can catch a missing alt attribute, an empty value used in the wrong place, or other structural problems. They cannot reliably decide whether the text gives a screen reader user the information needed to understand or use the page.\n\nThat distinction is the focus of the GitHub Accessibility Scanner plugin described in the source post: accessibility tooling should help teams evaluate the meaning of alternative text, not merely its presence.\n\n## An alt Attribute Is Only the Starting Point\n\nAll of these examples may satisfy a basic rule that checks for an alt attribute:\n\nhtml\n<img src=\"chart.png\" alt=\"chart\">\n<img src=\"team.jpg\" alt=\"team photo\">\n<img src=\"warning.svg\" alt=\"warning icon\">\n\n\nThey still leave important questions unanswered. What does the chart show? Who is in the photo, and why is it on the page? Is the warning icon decorative, or does it communicate that an operation failed?\n\nA useful review starts by identifying the image's role:\n\n1. Informational images should convey the content a user needs for the task.\n2. Functional images should describe the action or destination, not just the visual object.\n3. Decorative images generally need an empty alt=\"\" so assistive technology can skip them.\n4. Complex images, such as charts, need a short summary plus accessible detail elsewhere when the detail matters.\n\nAutomation is good at checking whether a field exists. Contextual review is what determines whether the field answers the user's question.\n\n## Put Content Review Into the Development Workflow\n\nA practical process has two gates. Let CI or an editor plugin catch structural errors quickly, then review the meaning of higher-risk cases in context.\n\nThe following small script can serve as a project-specific starting point. Before running it, replace the file arguments with the HTML files used by your project. It intentionally flags generic wording for human review instead of pretending to understand every image.\n\npython\nfrom pathlib import Path\nimport re\nimport sys\n\nGENERIC_ALT = {\n \"image\", \"photo\", \"picture\", \"graphic\",\n \"image of\", \"photo of\", \"icon\",\n}\n\nIMG_RE = re.compile(r\"<img\\b[^>]*>\", re.IGNORECASE)\nALT_RE = re.compile(r\"\\balt\\s*=\\s*([\\\"'])(.*?)\\1\", re.IGNORECASE | re.DOTALL)\n\ndef review(path: Path) -> list[str]:\n html = path.read_text(encoding=\"utf-8\")\n problems = []\n\n for number, tag in enumerate(IMG_RE.findall(html), start=1):\n match = ALT_RE.search(tag)\n if match is None:\n problems.append(f\"{path}: image {number} is missing alt\")\n continue\n\n alt = \" \\".join(match.group(2).split()).strip()\n if alt.lower() in GENERIC_ALT:\n problems.append(f\"{path}: image {number} has generic alt: {alt!r}\")\n elif len(alt) > 160:\n problems.append(f\"{path}: image {number} alt is too long; consider nearby details\")\n\n return problems\n\npaths = [Path(name) for name in sys.argv[1:]]\nerrors = [problem for path in paths for problem in review(path)]\nfor error in errors:\n print(error)\n\nsys.exit(1 if errors else 0)\n\n\nThis is deliberately modest. A production implementation could also: track approved decorative-image exceptions, inspect accessible names for image-only buttons and links, require a data table or summary for charts, and record human review decisions in code review or issue tracking.\n\n## The Value of a Purpose-Built Plugin\n\nA plugin is useful when it brings content quality into a workflow developers already use. The best feedback identifies the exact element, explains the likely risk, and gives enough context to choose the right fix: rewrite the alternative text, add nearby explanatory content, or mark the image as decorative.\n\nConsider a chart showing release latency. These two versions are structurally similar but not equally useful:\n\nhtml\n<!-- The attribute exists, but the information is too vague. -->\n<img src=\"latency.png\" alt=\"latency chart\">\n\n<!-- A concise summary; provide detailed data in text or a table when needed. -->\n<img\n src=\"latency.png\"\n alt=\"Release latency fell from 18 minutes in January to 7 minutes in March, after a brief rise to 12 minutes in February.\"\n>\n\n\nThe second version is not automatically correct in every context. A chart used for a decision may need a data table or a fuller text explanation. A purely decorative image should use empty alternative text instead. The tool can identify where judgment is needed; it cannot replace understanding the page's purpose.\n\n## A Short Review Checklist\n\nBefore submitting a component or page, ask:\n\n- What is the image's role: informational, functional, decorative, or complex content?\n- Does informational alternative text convey task-relevant content rather than merely saying “this is an image”?\n- Does functional alternative text describe the result of activating the control?\n- Are decorative images skipped with an empty alt value?\n- Do charts, diagrams, and screenshots have an accessible summary and, when necessary, detailed alternatives?\n- Can the content be understood without relying on color, position, or visual-only details?\n- After automated checks pass, has someone reviewed representative examples in page context?\n\nTreat automated scanning as a baseline, not a quality certificate. Good alt text is not text that produces no warning; it is text that gives a screen reader user enough relevant information to complete the same task as other users.","seo_description_en":"Learn why passing automated alt-text checks is not enough, and how plugins, CI rules, and contextual review can improve accessibility."}


相关推荐