Skip to content
WCAG 1.1.1 Non-text Content

How to fix: Images must have alt text

Every meaningful image needs alt text so screen-reader users know what it shows. Decorative images get an empty alt attribute so they are skipped.

The fix

Add a descriptive alt attribute to every <img>. Use alt="" only for purely decorative images.

Who this affects

When the alt attribute is missing altogether, NVDA and JAWS fall back to the file name, so a product photo is announced as "graphic, DSC underscore 4471 dot jpg". A person reading on a braille display gets that same string spelled out, and someone who relies on the alt text to decide whether to open a larger view has nothing to go on. Sighted visitors hit the same wall whenever the image request fails or is blocked, because there is no text left in the gap.

Before and after

Fails
<img src="team.jpg">
Passes
<img src="team.jpg" alt="Our support team answering customer calls">

Where this usually comes from

  • A Blade or Twig template that omits the attribute entirely when the alt field is empty instead of printing alt="".
  • Image data from a CMS or API where the alt key is undefined, which React and Vue then drop from the rendered tag.
  • Editors uploading through a media library or WYSIWYG that treats the alt field as optional and never prompts.
  • alt=" " with a single space, used to hide an image from screen readers; axe flags whitespace-only alt separately from a missing one.
  • A wrapper image component built for lazy loading or an image CDN that spreads props but never forwards alt.

Checking it yourself

Run [...document.querySelectorAll('img')].filter(img => !img.hasAttribute('alt') || (img.alt.trim() === '' && img.alt !== '')) in the console to catch the missing attribute and the whitespace-only alt=" " together, then find each one on the page and decide whether it carries information or is decoration; an image named by aria-label, title or role="presentation" turns up in that list without being a failure.

A scanner finds this one automatically. What it cannot judge, and how the score is built, is on how we test.

Related fixes

Check your site for this issue

Scan any page free against WCAG 2.2 AA and get every automatically detected issue with its fix.

Scanning a page needs no account. The checks run on axe-core.

← All fix guides