image-alt-text
Load this skill whenever the project contains <img> elements, inline SVGs used as content images, CSS background images that convey meaning, or icon fonts. Under no circumstances omit alt text on meaningful images. Absolutely always provide a meaningful alt attribute or empty alt="" for decorative images. Apply WCAG 2.2 SC 1.1.1 — every non-text element requires a text alternative.
Image Alt Text Accessibility Skill
Canonical source:
examples/IMAGE_ALT_TEXT_ACCESSIBILITY_BEST_PRACTICES.mdinmgifford/ACCESSIBILITY.mdThis skill is derived from that file. When in doubt, the example is authoritative.
Apply these rules when creating, reviewing, or auditing any page containing images.
Only load this skill if the project contains <img> elements, inline SVG images used as content, or CSS background images that may convey meaning.
Core Mandate
WCAG 2.2 Success Criterion 1.1.1 — Non-text Content (Level A): every non-text element must have a text alternative conveying the same meaning and purpose. There are no exceptions for decorative images — those require an explicit empty alt attribute.
Automated tools can flag missing alt text, but only human judgment can determine whether alt text is meaningful and appropriate for the context.
Severity Scale (this skill)
| Level | Meaning |
|---|---|
| Critical | Image conveying essential meaning has no alt attribute, or alt is entirely absent |
| Serious | Functional image (button/link) has no text alternative, preventing keyboard/screen reader use |
| Moderate | Alt text is present but inaccurate, redundant ("image of…"), or missing meaningful context |
| Minor | Alt text is slightly verbose or could be improved but does not prevent understanding |
The Alt Text Decision Tree
Use this flowchart (based on the W3C WAI Images Tutorial):
Does the image contain text?
├── YES → Use the same text as the alt attribute (unless decorative/logo)
└── NO
└── Is the image used for a functional purpose (link, button)?
├── YES → Describe the destination/action (e.g., "Go to homepage")
└── NO
└── Does the image convey information not present in surrounding text?
├── YES
│ └── Is the image complex (chart, diagram, graph)?
│ ├── YES → Provide a short alt + long description in nearby text
│ └── NO → Write a concise description of the content and meaning
└── NO
└── Is the image purely decorative or redundant?
├── YES → Use empty alt: alt=""
└── NO → Re-evaluate — the image likely carries meaning
Image Categories and Requirements
Informative Images
Images that convey information not expressed in surrounding text.
<!-- DO: Describe the meaning/content -->
<img src="quarterly-growth.png" alt="Bar chart showing 23% revenue growth in Q3 2024">
<!-- DON'T: Describe visual appearance only -->
<img src="quarterly-growth.png" alt="Blue and green bar chart">
<!-- DON'T: Use file names or generic labels -->
<img src="quarterly-growth.png" alt="quarterly-growth.png">
<img src="quarterly-growth.png" alt="image">
Decorative Images
Images that are purely aesthetic and add no information beyond what the page text already provides.
<!-- DO: Empty alt for decorative images -->
<img src="decorative-divider.png" alt="">
<!-- DO: aria-hidden for inline SVG decorations -->
<svg aria-hidden="true" focusable="false">...</svg>
<!-- DON'T: Omit alt entirely — screen readers announce the filename -->
<img src="decorative-divider.png">
<!-- DON'T: Use "decorative" or "spacer" as alt text -->
<img src="decorative-divider.png" alt="decorative">
When is an image truly decorative? Only if it is purely aesthetic (border, texture, flourish), adds no information beyond surrounding text, and removing it would not affect a user's understanding.
If you are debating whether an image is decorative, it probably is not. When in doubt, provide alt text. The cost of unnecessary alt text is low; the cost of missing alt text can be complete loss of meaning.
Functional Images
Images that are the only content of a link or button.
<!-- DO: Describe the link destination -->
<a href="/home">
<img src="logo.svg" alt="Go to homepage">
</a>
<!-- DO: Describe the button action -->
<button>
<img src="search-icon.svg" alt="Search">
</button>
<!-- DO: Use aria-label on the button, empty alt on the image -->
<button aria-label="Search">
<img src="search-icon.svg" alt="">
</button>
<!-- DON'T: Leave functional images with empty alt (creates unlabelled control) -->
<button>
<img src="search-icon.svg" alt="">
<!-- Missing accessible name — use aria-label on the button instead -->
</button>
Complex Images
Charts, graphs, diagrams, maps, and infographics where a short alt cannot convey all information.
<!-- Pattern 1: Alt summary + adjacent long description -->
<figure>
<img
src="accessibility-adoption-chart.png"
alt="Line chart: WCAG AA adoption rose from 38% in 2020 to 67% in 2024"
aria-describedby="chart-desc">
<figcaption id="chart-desc">
Annual WCAG 2.1 Level AA adoption rates from 2020 to 2024 across a sample
of 10,000 public websites. Adoption grew steadily from 38% (2020) to 67%
(2024), driven by increased procurement requirements.
</figcaption>
</figure>
Images of Text
<!-- DO: Reproduce the exact text in the alt attribute -->
<img src="sale-banner.png" alt="Summer Sale: 50% off all items through July 31">
<!-- DON'T: Describe that it is text -->
<img src="sale-banner.png" alt="Sale banner showing promotional text">
Prefer actual text over images of text whenever possible (WCAG 1.4.5).
Groups of Images
When multiple images work together to convey a single piece of information (e.g., a star rating):
<!-- Star rating: 4 out of 5 stars — only the first image needs meaningful alt -->
<img src="star-filled.png" alt="Rating: 4 out of 5 stars">
<img src="star-filled.png" alt="">
<img src="star-filled.png" alt="">
<img src="star-filled.png" alt="">
<img src="star-empty.png" alt="">
Linked Images with Adjacent Text
When an image and text are together inside the same link:
<!-- DO: Empty alt when link text describes the destination -->
<a href="/articles/accessibility-guide">
<img src="accessibility-thumbnail.jpg" alt="">
<span>The Complete Accessibility Guide</span>
</a>
<!-- DON'T: Duplicate the link text in alt -->
<a href="/articles/accessibility-guide">
<img src="accessibility-thumbnail.jpg" alt="The Complete Accessibility Guide">
The Complete Accessibility Guide
</a>
Writing Quality Alt Text
- Be concise but complete. Aim for 125 characters or fewer for simple images; use long descriptions for complex images.
- Describe content and purpose, not appearance. "Person in a wheelchair using a laptop" is more useful than "image of a person".
- Context is everything. The same image can have different alt text depending on how it is used.
- Do not start with "Image of", "Picture of", or "Photo of". Screen readers already announce that they are reading an image.
- Avoid keyword stuffing. Alt text serves users, not search engines.
- Include text that appears within the image.
- Match the level of detail to the image's role.
Common Bad Alt Text Patterns (Critical/Serious to flag and fix)
Missing or absent alt attribute — Critical
<!-- WRONG: Screen reader reads the filename -->
<img src="Q3-revenue-chart-final-v2.png">
<!-- RIGHT -->
<img src="Q3-revenue-chart-final-v2.png"
alt="Bar chart: Q3 2024 revenue reached $4.2M, up 18% from Q2">
Filename or CMS-injected alt text — Serious
<!-- WRONG -->
<img src="golden-retriever.jpg" alt="golden-retriever.jpg">
<img src="dog.png" alt="This image has an empty alt attribute; its file name is dog.png">
Generic single-word placeholders — Serious
The following values are flagged as errors by multiple accessibility checkers:
<!-- WRONG -->
<img src="photo.jpg" alt="image">
<img src="photo.jpg" alt="photo">
<img src="photo.jpg" alt="graphic">
<img src="photo.jpg" alt="chart">
<img src="photo.jpg" alt="alt">
<img src="spacer.gif" alt="spacer"> <!-- use alt="" instead -->
<img src="divider.png" alt="decorative"> <!-- use alt="" instead -->
Draft/placeholder text — Serious
<!-- WRONG -->
<img src="portrait.jpg" alt="TBD">
<img src="portrait.jpg" alt="TODO">
<img src="portrait.jpg" alt="placeholder">
<img src="portrait.jpg" alt="null">
<img src="portrait.jpg" alt="undefined">
"Type" prefix phrases — Moderate
<!-- WRONG: Redundant medium prefix -->
<img src="team-photo.jpg" alt="Image of the team">
<img src="team-photo.jpg" alt="Photo of team members">
<!-- RIGHT -->
<img src="team-photo.jpg" alt="The Civic Innovations team of 12 staff gathered outside City Hall">
Alt text that duplicates a figcaption — Moderate
<!-- WRONG: Screen reader announces the text twice -->
<figure>
<img src="annual-report-cover.jpg"
alt="2024 Annual Report cover showing the city skyline at dusk">
<figcaption>2024 Annual Report cover showing the city skyline at dusk</figcaption>
</figure>
<!-- RIGHT: Caption fully describes — use empty alt -->
<figure>
<img src="annual-report-cover.jpg" alt="">
<figcaption>2024 Annual Report cover showing the city skyline at dusk</figcaption>
</figure>
Name-only alt for person portraits — Moderate
<!-- POOR: Name only -->
<img src="j-smith.jpg" alt="J Smith">
<!-- BETTER: Include role and context -->
<img src="j-smith.jpg"
alt="Dr. Jane Smith, Chief Medical Officer, presenting at the 2024 health summit">
CSS Background Images
CSS background-image does not support alt text. Use only for decorative purposes.
/* OK: Decorative pattern */
.hero { background-image: url('geometric-pattern.svg'); }
<!-- NOT OK: Meaningful image as CSS background (invisible to screen readers) -->
<div style="background-image: url('award-badge.png')"></div>
<!-- DO: Use <img> for meaningful images -->
<img src="award-badge.png" alt="Winner: Best Accessibility Tool 2024">
Automated vs. Human Testing
| Automated tools can detect | Requires human review |
|---|---|
Missing alt attribute | Whether alt text is meaningful |
| Empty alt on functional images | Whether alt text matches context |
| Alt text that equals the file name | Whether a decorative image actually needs alt text |
| Suspicious prefix phrases ("image of") | Whether the description conveys the right meaning |
| Known placeholder values ("TBD", "null") | Whether content-author intent was decorative or informative |
| Alt text identical to adjacent figcaption | Whether the alt or the caption should be kept |
Automated tools such as axe-core detect structural issues. Human review is always required to evaluate quality.
Definition of Done Checklist
- Every
<img>element has analtattribute (even decorative images usealt="") - Decorative images use
alt=""and are confirmed to add no meaning - Functional images (links, buttons) describe the action or destination
- Alt text does not begin with "image of", "picture of", or "photo of"
- Alt text does not repeat the file name or generic label ("image", "photo", "graphic", "chart")
- Alt text is not a draft placeholder ("TBD", "TODO", "null", "none", "undefined", "placeholder")
- Alt text is not a machine-generated code or CMS-injected message
- Complex images (charts, diagrams) have both a short alt and a long description
- Images of text reproduce the exact text in the
altattribute - Grouped images convey combined meaning via one image's alt (others are
alt="") - Linked images with adjacent link text use
alt=""on the image - Figures with a
<figcaption>do not duplicate the caption verbatim in thealt - Portrait images include the person's role and context, not just their name
- CSS background images are decorative (meaningful images use
<img>) - Alt text has been reviewed in context, not just in isolation
- Alt text has been tested with a screen reader (NVDA + Firefox or VoiceOver + Safari)
Key WCAG Criteria
- 1.1.1 Non-text Content (A) — Critical if any meaningful image has no text alternative
- 1.4.5 Images of Text (AA) — prefer real text over images of text
- 1.4.9 Images of Text (No Exception) (AAA)
- 4.1.2 Name, Role, Value (A) — all UI components have accessible names and roles
References
- Full best practices guide
- W3C WAI — Images Tutorial and Decision Tree
- WCAG 2.2 — 1.1.1 Non-text Content
- WebAIM — Writing Effective Alt Text
- Sa11y — flags suspicious alt text patterns
- Editoria11y — CMS-focused alt text checking
- axe-core rules:
image-alt,image-redundant-alt,input-image-alt,area-alt,object-alt