WCAG 2.1 Image Accessibility: What Developers Need to Know
WCAG 2.1 and Images: The Developer's Responsibility
Web accessibility is not just a design concern -- it is an engineering requirement. As a developer, you are the last line of defense between a mockup and what actually ships to users. When it comes to images, WCAG 2.1 has specific, testable criteria that determine whether your implementation is accessible or not.
This guide covers the WCAG success criteria that apply to images, with practical code examples you can use directly in your projects.
The Relevant Success Criteria
1.1.1 Non-text Content (Level A)
This is the primary criterion for images. It requires that all non-text content has a text alternative that serves the equivalent purpose. "Level A" means this is the minimum baseline -- every accessibility standard and legal framework requires it.
What it means in practice: every <img> element must have an alt attribute. But the value of that attribute depends on the image's purpose.
1.4.5 Images of Text (Level AA)
If an image contains text, that text should be presented as actual text rather than an image, except where the visual presentation is essential (logos, for example). When you must use an image of text, the alt text must contain the same text.
1.4.9 Images of Text -- No Exception (Level AAA)
The stricter version: images of text are only used for pure decoration or where a particular presentation of text is essential to the information being conveyed. Most teams target Level AA, but Level AAA conformance means eliminating almost all images of text.
Image Categories and How to Handle Them
Informative Images
These are images that convey information, illustrate concepts, or complement text content. They are the most common type on the web.
<!-- Simple informative image -->
<img
src="/images/solar-panel-installation.jpg"
alt="Technician installing solar panels on a residential rooftop"
/>
<!-- Product image with specific details -->
<img
src="/images/ceramic-mug.jpg"
alt="Handmade blue ceramic coffee mug with speckled glaze, 12 oz capacity"
/>
<!-- Image that supplements surrounding text -->
<img
src="/images/quarterly-team-photo.jpg"
alt="AltFrame engineering team at the Q4 2025 offsite in Portland"
/>Key rules for informative images:
- Alt text should convey the same information the image communicates visually
- Be specific but concise -- aim for one sentence, rarely more than two
- Do not start with "Image of" or "Picture of" -- screen readers already announce it as an image
- Include relevant details a sighted user would notice
Decorative Images
Decorative images serve no informational purpose. They are visual embellishments: background textures, divider lines, purely aesthetic photographs. These should be hidden from assistive technology.
<!-- Decorative image: use empty alt -->
<img src="/images/decorative-wave.svg" alt="" />
<!-- Even better: use CSS for purely decorative visuals -->
<div class="hero-section" style="background-image: url('/images/abstract-bg.jpg')">
<!-- Content here -->
</div>
<!-- Decorative icon next to text that already describes it -->
<p>
<img src="/icons/checkmark.svg" alt="" aria-hidden="true" />
Payment confirmed
</p>Critical distinction: An empty alt="" is not the same as a missing alt attribute.
alt=""tells screen readers "this image is decorative, skip it." This is correct for decorative images.- A missing
altattribute causes screen readers to read the file name or URL, which is never helpful.
Complex Images: Charts, Graphs, and Diagrams
Complex images convey data or relationships that cannot be adequately described in a short alt text. These require both a brief alt text summary and an extended description.
<!-- Approach 1: aria-describedby with a visible description -->
<figure>
<img
src="/images/revenue-chart-q4.png"
alt="Bar chart showing quarterly revenue for 2025"
aria-describedby="chart-desc"
/>
<figcaption id="chart-desc">
Revenue grew from $2.1M in Q1 to $3.8M in Q4 2025, representing
81% year-over-year growth. Q3 saw the largest quarter-over-quarter
increase at 28%, driven by the launch of the enterprise tier.
</figcaption>
</figure>
<!-- Approach 2: Link to a detailed description -->
<figure>
<img
src="/images/system-architecture.png"
alt="System architecture diagram showing data flow between services"
/>
<figcaption>
<a href="#architecture-details">Detailed architecture description</a>
</figcaption>
</figure>
<!-- Approach 3: details/summary for collapsible long description -->
<figure>
<img
src="/images/survey-results.png"
alt="Pie chart of developer tool preferences from 2025 survey"
aria-describedby="survey-details"
/>
<details id="survey-details">
<summary>View chart data</summary>
<table>
<tr><th>Tool</th><th>Percentage</th></tr>
<tr><td>VS Code</td><td>48%</td></tr>
<tr><td>JetBrains IDEs</td><td>27%</td></tr>
<tr><td>Neovim</td><td>12%</td></tr>
<tr><td>Other</td><td>13%</td></tr>
</table>
</details>
</figure>Guidelines for complex images:
- The
altattribute provides a brief summary (what type of image and its general topic) - The extended description provides the actual data or detailed explanation
- Use
aria-describedbyto programmatically associate the description with the image - When possible, also provide the data in a table format for maximum accessibility
Images of Text
When text is rendered as an image (banners, stylized headings, logos), the alt text must include the text shown in the image.
<!-- Logo with company name -->
<img src="/images/company-logo.svg" alt="AltFrame" />
<!-- Banner with promotional text -->
<img
src="/images/sale-banner.jpg"
alt="Summer Sale: 30% off all products through August 31"
/>
<!-- Avoid this pattern when possible -- use real text + CSS instead -->
<!-- Bad: image of a heading -->
<img src="/images/our-mission-heading.png" alt="Our Mission" />
<!-- Good: actual text with CSS styling -->
<h2 class="font-display text-4xl gradient-text">Our Mission</h2>Image Maps
Image maps use clickable regions within a single image. Both the image and each active area need text alternatives.
<img
src="/images/office-floor-plan.png"
alt="Interactive floor plan of the Portland office"
usemap="#floorplan"
/>
<map name="floorplan">
<area
shape="rect"
coords="0,0,200,150"
href="/rooms/conference-a"
alt="Conference Room A - seats 12"
/>
<area
shape="rect"
coords="200,0,400,150"
href="/rooms/kitchen"
alt="Kitchen and break area"
/>
<area
shape="circle"
coords="300,300,50"
href="/rooms/phone-booth-1"
alt="Phone booth 1 - single occupancy"
/>
</map>Linked Images
When an image is the sole content of a link, the alt text must describe the link's destination or purpose, not the image itself.
<!-- Image is the only content in the link -->
<a href="/products/widget-pro">
<img src="/images/widget-pro.jpg" alt="View Widget Pro product details" />
</a>
<!-- Image alongside text in a link: image can be decorative -->
<a href="/products/widget-pro">
<img src="/images/widget-pro.jpg" alt="" />
<span>Widget Pro</span>
</a>Common Mistakes and How to Fix Them
Mistake 1: Redundant Alt Text
<!-- Bad: alt repeats the caption exactly -->
<figure>
<img src="/photo.jpg" alt="Team celebrating product launch" />
<figcaption>Team celebrating product launch</figcaption>
</figure>
<!-- Better: alt adds detail the caption does not -->
<figure>
<img src="/photo.jpg" alt="Eight team members raising glasses around a conference table decorated with streamers" />
<figcaption>Team celebrating product launch</figcaption>
</figure>Mistake 2: Over-Describing
<!-- Bad: too verbose -->
<img alt="This is a photograph of a white coffee cup with a black handle sitting on a round wooden table with a newspaper and a pair of reading glasses next to it in what appears to be a cafe with natural lighting coming from a window on the left side" />
<!-- Better: concise and relevant -->
<img alt="Coffee cup and newspaper on a cafe table in morning light" />Mistake 3: Missing Alt on Functional Images
<!-- Bad: icon button with no accessible name -->
<button>
<img src="/icons/search.svg" />
</button>
<!-- Good: alt text provides the button's label -->
<button>
<img src="/icons/search.svg" alt="Search" />
</button>
<!-- Also good: aria-label on the button, decorative image -->
<button aria-label="Search">
<img src="/icons/search.svg" alt="" />
</button>Testing Tools and Techniques
Automated Testing
- axe DevTools (browser extension): Flags images missing alt attributes, images with suspicious alt text (file names, single words), and linked images without text alternatives.
- Lighthouse (Chrome DevTools): The accessibility audit catches missing alt attributes and provides WCAG references.
- Pa11y: Command-line accessibility testing that can be integrated into CI/CD pipelines.
- jest-axe: For React applications, add accessibility assertions to unit tests:
import { axe, toHaveNoViolations } from "jest-axe";
expect.extend(toHaveNoViolations);
test("product card is accessible", async () => {
const { container } = render(<ProductCard />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});Manual Testing
- Screen reader testing: Use VoiceOver (macOS), NVDA (Windows), or Orca (Linux) to navigate your pages. Listen to how images are announced. Is the description useful? Is it too long? Are decorative images properly hidden?
- Image-off browsing: Disable images in your browser and check if the alt text alone conveys the necessary information.
- Keyboard navigation: Ensure linked images and image maps are reachable and usable via keyboard alone.
CI/CD Integration
Catch accessibility regressions automatically by adding accessibility checks to your deployment pipeline:
# GitHub Actions example
- name: Accessibility audit
run: |
npx pa11y-ci --config pa11y-config.jsonThis catches new images without alt text before they reach production.
A Practical Decision Framework
When you encounter an image in your code, ask these questions in order:
- Does this image convey information? If no, use
alt=""(decorative). - Is this image the sole content of a link? If yes, alt text describes the link destination.
- Is this a complex image (chart, diagram, infographic)? If yes, provide short alt + extended description.
- Is this an image of text? If yes, alt text contains the same text. Consider using real text instead.
- For everything else: Write a concise, descriptive alt text that conveys what the image communicates.
For teams managing large image libraries, automating alt text generation with tools like AltFrame and then applying human review for edge cases (complex images, decorative determinations) is the most practical path to full WCAG compliance at scale.
The standard is clear. The techniques are well-established. What most teams lack is not knowledge but process -- a systematic way to ensure every image that ships has the right text alternative. Build that process into your workflow, and accessibility becomes a natural part of development rather than an afterthought.