1.1.1 Non-text Content

WCAG 2.2 · 1.1.1 A Perceivable

What it requires

All non-text content presented to the user must have a text alternative that serves the equivalent purpose. Non-text content means images, icons, charts, image buttons, image maps, audio, video, CAPTCHAs, ASCII art, emojis used as content, and similar. The text alternative is what assistive technology reads aloud, shows on a braille display, or falls back to when the image fails to load.

The criterion allows specific exceptions, each with its own rule:

  • Controls and inputs — give a name that describes their purpose (for example, an icon-only search button needs an accessible name like “Search”).
  • Time-based media (audio/video) — the text alternative at least identifies the media; full alternatives are covered by the 1.2.x criteria.
  • Tests or sensory experiences — provide text that at least describes and identifies the content.
  • CAPTCHA — describe its purpose and provide alternative forms for different disabilities.
  • Decoration, formatting, or invisible content — must be implemented so assistive technology can ignore it (an empty alt="" or aria-hidden).

  • Blind and low-vision screen-reader users — without alt text, an image is announced as “image”, a filename, or nothing, so its meaning is lost.
  • People who turn off images or are on slow or failed connections — they rely on the fallback text.
  • People with cognitive disabilities who benefit from text that supports or replaces complex visuals.
  • Deafblind users reading via a braille display, who receive only the text alternative.

How to detect it

Manual and tool-based checks
Check What to look for Automated?
Missing alt Any <img> with no alt attribute at all. Yes — axe and similar flag it reliably.
Empty name on controls Icon-only buttons or links with no text and no aria-label. Yes — empty accessible name is detectable.
Quality of alt text Whether the alt actually conveys meaning, or is a filename / “image”. No — requires human judgement.
Decorative images Purely decorative images should have alt="", not a description. Partly — tools cannot judge intent.
Screen-reader pass Navigate by images/controls; confirm each is announced meaningfully. No — manual AT testing.

How to fix it

  1. Give every informative image an alt that conveys its purpose, not its appearance or filename.
  2. Mark decorative images with empty alt="" (or hide via CSS / aria-hidden) so they are skipped.
  3. Give icon-only controls an accessible name with visible text or aria-label.
  4. For complex images (charts, diagrams), provide a longer description nearby or via aria-describedby.
  5. For audio/video, at minimum identify the media in text (and meet 1.2.x).
<!-- Informative image: alt conveys purpose -->
<img src="chart.png" alt="Sales rose 40% from Q1 to Q2">

<!-- Decorative image: empty alt, skipped by AT -->
<img src="divider.png" alt="">

<!-- Icon-only button: name describes its action -->
<button type="submit" aria-label="Search">
  <svg aria-hidden="true" focusable="false"><!-- … --></svg>
</button>

Copy-paste tests

Automated coverage

These axe-core rules flag failures of this criterion: aria-meter-name, aria-progressbar-name, image-alt, input-image-alt, object-alt, role-img-alt, and svg-img-alt. Run them via the axe DevTools browser extension or axe-core in CI. Automated tools only catch some failures, so pair them with the manual checks below.

Run this in the browser console

check-non-text.js
// Read-only: lists non-text content that may lack a text alternative.
const suspects = [...document.querySelectorAll(
  'img:not([alt]), svg:not([aria-label]):not([aria-labelledby]):not([role=presentation]):not([aria-hidden=true]), ' +
  'button:empty:not([aria-label]):not([aria-labelledby]), a:empty:not([aria-label]):not([aria-labelledby]), ' +
  'input[type=image]:not([alt]):not([aria-label]), object:not([aria-label]):not([aria-labelledby])'
)];
console.table(suspects.map(el => ({ tag: el.tagName, alt: el.getAttribute('alt'), label: el.getAttribute('aria-label'), html: el.outerHTML.slice(0, 80) })));
suspects.forEach(el => { el.style.outline = '2px solid red'; });
console.log('Suspect non-text nodes:', suspects);

What to check manually: confirm each alt conveys the image's purpose (not its filename or “image”), and that images marked alt="" are genuinely decorative — no script can judge meaning or intent.