Skip to main content
WCAG Patterns

WCAG 1.1.1 · Level A · WCAG 2.0

Non-text Content

Every image, icon, chart, form control, and embedded media needs a text alternative that conveys the same purpose — so screen readers, braille displays, and text-only browsers can access it.

Principle
Perceivable
Guideline
Text Alternatives
Level
A
Added in
WCAG 2.0

What it really means

Every piece of non-text content — images, icons, charts, form controls, audio, video, CAPTCHAs, embedded media — must have a text alternative that conveys the same purpose. Not the same literal description. The same purpose.

A magnifying-glass icon inside a search button isn't "magnifying glass" — it's "Search". A chart isn't "bar chart with four columns" — it's the insight the chart is meant to convey ("Revenue rose 38% in Q4"). The text alternative answers the question: if this image vanished, what would a sighted user have learned from it?

Who it helps

  • Blind screen-reader users get a usable alternative.
  • Low-vision users who turn off images for speed still know what was there.
  • Deaf users get transcripts or captions for audio-only content.
  • Everyone on a flaky connection who sees a broken-image placeholder.
  • Search engines, which read alt text like you do.

How to test

  1. Turn on VoiceOver (⌘F5 on macOS) or NVDA (free on Windows) and navigate images with your screen reader's list-images command. Every meaningful image should announce a purpose — not a filename.
  2. Run axe DevTools — the image-alt rule flags anything missing alt.
  3. In Chrome DevTools → Accessibility pane, inspect the computed name for each <img>, <svg role="img">, <input type="image">, and icon button.

A failing pattern

// Missing alt — screen readers announce the filename or nothing.
<img src="/hero.jpg" />
 
// Decorative logo with descriptive alt — double-announced with the
// company name next to it in the header.
<img src="/acme-logo.svg" alt="Acme Corp logo — blue mountain icon" />
 
// Icon-only button with no accessible name.
<button onClick={openSearch}>
  <SearchIcon />
</button>

A passing pattern

// Meaningful hero image — alt describes what it shows (the purpose).
<img
  src="/hero.jpg"
  alt="Product screenshot: accessibility scanner highlighting focus order on a page."
/>
 
// Decorative logo — empty alt so AT skips it.
<img src="/acme-logo.svg" alt="" aria-hidden="true" />
 
// Icon-only button — visible icon, accessible name via aria-label.
<button type="button" aria-label="Search" onClick={openSearch}>
  <SearchIcon aria-hidden="true" />
</button>

For SVGs rendered inline, mark the graphic with role="img" and either aria-label or an in-SVG <title> element as the first child:

<svg role="img" aria-labelledby="chart-title" viewBox="0 0 400 200">
  <title id="chart-title">Revenue rose 38 percent in Q4 2025.</title>
  {/* chart path data */}
</svg>