View contents
Introduction
Alt text (alternative text) provides a text description of images for users who cannot see them. This includes people using screen readers, those with images disabled, and search engine crawlers. WCAG 2.2 Success Criterion 1.1.1 (Non-text Content) is a Level A requirement—the most fundamental accessibility standard.
Writing effective alt text is both an art and a science. It requires understanding the image’s purpose in context and communicating that purpose concisely to users who can’t see it.
What Is Alt Text?
The HTML Attribute
Alt text is added to images using the alt attribute:
<img src="chart.png" alt="Bar chart showing 40% increase in sales Q3 2024">
Types of Images and Their Alt Text
| Image Type | Alt Text Approach | Example |
|---|---|---|
| Informative | Describe content and meaning | “Red warning icon” |
| Functional | Describe the action/destination | “Submit form” |
| Decorative | Use empty alt (alt=“”) | Background patterns |
| Complex | Brief alt + longer description | Charts, diagrams |
| Text in images | Include all visible text | Logos, banners |
Why Alt Text Matters
Who Benefits
- Screen reader users - Primary consumers of alt text
- Users with slow connections - See description before image loads
- Search engines - Understand image content for indexing
- Users with images disabled - Still get content meaning
SEO Benefits
Alt Text SEO Impact:
┌─────────────────────────────────────────────────────────┐
│ Image Search Rankings → Better alt text = more traffic │
│ Page Context → Helps Google understand page content │
│ Crawl Efficiency → Text is faster to process │
│ Accessibility Score → Affects Core Web Vitals │
└─────────────────────────────────────────────────────────┘
Legal Compliance
Alt text is required under:
- WCAG 2.2 Level A (Success Criterion 1.1.1)
- ADA (Americans with Disabilities Act)
- Section 508 (US Federal requirements)
- EN 301 549 (European accessibility standard)
Common Alt Text Mistakes
1. Missing Alt Attributes
<!-- BAD: No alt attribute -->
<img src="product.jpg">
<!-- GOOD: Descriptive alt text -->
<img src="product.jpg" alt="Blue wireless headphones with noise cancellation">
2. Redundant Descriptions
<!-- BAD: Redundant "image of" -->
<img src="team.jpg" alt="Image of our team at the office">
<!-- GOOD: Direct description -->
<img src="team.jpg" alt="Our team collaborating around a whiteboard">
3. Keyword Stuffing
<!-- BAD: SEO spam -->
<img src="shoes.jpg" alt="Buy shoes online best shoes cheap shoes sale shoes">
<!-- GOOD: Natural description -->
<img src="shoes.jpg" alt="Men's black leather oxford dress shoes">
4. Generic Descriptions
<!-- BAD: Not helpful -->
<img src="data.png" alt="Chart">
<!-- GOOD: Conveys the data -->
<img src="data.png" alt="Line chart showing user growth from 10K to 50K over 12 months">
5. Decorative Images Without Empty Alt
<!-- BAD: Decorative image with description -->
<img src="divider.png" alt="Decorative line divider">
<!-- GOOD: Empty alt for decorative images -->
<img src="divider.png" alt="">
Writing Good Alt Text
The Decision Tree
Ask yourself:
│
├─ Is this image purely decorative?
│ └─ YES → Use alt=""
│
├─ Does the image contain text?
│ └─ YES → Include all text in alt
│
├─ Is the image a link or button?
│ └─ YES → Describe destination/action
│
├─ Does surrounding text describe the image?
│ └─ YES → Use brief alt or alt=""
│
└─ Otherwise → Describe content and purpose
Good Alt Text Principles
- Be concise - Usually 125 characters or less
- Be specific - Include relevant details
- Convey purpose - Why is this image here?
- Don’t start with “Image of…” - Screen readers announce images
- Consider context - Same image may need different alt text in different places
Examples by Context
E-commerce Product:
<img src="jacket.jpg" alt="Women's waterproof hiking jacket in forest green, sizes XS-XL">
News Article:
<img src="protest.jpg" alt="Thousands of protesters gathered in downtown plaza holding climate action signs">
Tutorial Step:
<img src="step3.png" alt="Click the blue 'Save' button in the top right corner">
Company Logo:
<img src="logo.png" alt="Acme Corporation">
Testing Alt Text
Screen Reader Testing
Test with actual screen readers:
- VoiceOver (macOS/iOS)
- NVDA (Windows, free)
- JAWS (Windows)
Automated Tools
| Tool | What It Checks |
|---|---|
| axe DevTools | Missing alt, empty alt on functional images |
| WAVE | Alt text presence and quality hints |
| Lighthouse | Image accessibility in audits |
Quick Manual Test
- Disable images in your browser
- Can you understand the page content?
- Does each image’s description make sense?
Quick Reference
Do’s and Don’ts
| Do | Don’t |
|---|---|
| Describe the image’s purpose | Start with “Image of…” |
| Be concise but complete | Keyword stuff |
| Use empty alt for decorative images | Leave alt attribute missing |
| Include text that appears in images | Use generic “photo” or “image” |
| Test with screen readers | Assume your alt text is good enough |
Implementation
Image Categories and Techniques
The WAI Images Decision Tree
┌─────────────────────────────────────────────────────────┐
│ WAI IMAGE ACCESSIBILITY DECISION │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. Does the image contain text? │
│ └─ YES → Include text in alt │
│ │
│ 2. Is the image used in a link or button? │
│ └─ YES → Describe function/destination │
│ │
│ 3. Does the image contribute meaning to context? │
│ └─ YES → Describe informational content │
│ │
│ 4. Is the image purely decorative? │
│ └─ YES → Use null alt (alt="") │
│ │
│ 5. Is the image complex (charts, diagrams)? │
│ └─ YES → Provide long description │
│ │
└─────────────────────────────────────────────────────────┘
Implementation by Image Type
1. Informative Images
Images that convey information or concepts:
<!-- Simple informative image -->
<img
src="warning-icon.png"
alt="Warning: This action cannot be undone"
>
<!-- Photo with context -->
<img
src="office-building.jpg"
alt="Modern glass office building with company logo at entrance"
>
<!-- Data visualization -->
<img
src="trend.png"
alt="Upward trending arrow indicating growth"
>
2. Decorative Images
Images that add no information content:
<!-- Method 1: Empty alt attribute (preferred) -->
<img src="decorative-border.png" alt="">
<!-- Method 2: CSS background (truly decorative) -->
<style>
.hero {
background-image: url('abstract-pattern.png');
}
</style>
<!-- Method 3: Role presentation (ARIA) -->
<img src="flourish.svg" alt="" role="presentation">
When is an image decorative?
- Background patterns and textures
- Spacer or design elements
- Icons next to text that says the same thing
- Mood/atmosphere images that don’t add information
3. Functional Images
Images used as links, buttons, or controls:
<!-- Linked logo -->
<a href="/">
<img src="logo.png" alt="Company Name - Go to homepage">
</a>
<!-- Image button -->
<button type="submit">
<img src="search-icon.svg" alt="Search">
</button>
<!-- Image link -->
<a href="/cart">
<img src="cart-icon.svg" alt="Shopping cart (3 items)">
</a>
<!-- Print button -->
<button onclick="window.print()">
<img src="print.svg" alt="Print this page">
</button>
4. Images of Text
Images containing readable text:
<!-- Logo with text -->
<img src="logo.png" alt="Acme Corporation">
<!-- Banner with message -->
<img
src="sale-banner.jpg"
alt="Summer Sale: 50% off all items through August 31"
>
<!-- Stylized heading -->
<img
src="welcome-text.png"
alt="Welcome to Our Store"
>
Best Practice: Use actual text with CSS styling instead of images of text when possible.
5. Complex Images
Charts, diagrams, graphs, and infographics:
<!-- Method 1: Brief alt + longdesc attribute -->
<img
src="org-chart.png"
alt="Organization chart showing company structure"
longdesc="org-chart-description.html"
>
<!-- Method 2: Brief alt + adjacent text description -->
<figure>
<img
src="sales-chart.png"
alt="Quarterly sales chart - details in table below"
>
<figcaption>
<details>
<summary>Sales data description</summary>
<p>Q1: $1.2M, Q2: $1.5M, Q3: $1.8M, Q4: $2.1M.
Total growth of 75% year-over-year.</p>
</details>
</figcaption>
</figure>
<!-- Method 3: aria-describedby -->
<img
src="process-flow.png"
alt="5-step checkout process"
aria-describedby="process-description"
>
<div id="process-description" class="sr-only">
Step 1: Add items to cart.
Step 2: Enter shipping address.
Step 3: Select shipping method.
Step 4: Enter payment information.
Step 5: Review and confirm order.
</div>
6. Groups of Images
Multiple images conveying a single piece of information:
<!-- Star rating -->
<div role="img" aria-label="Rating: 4 out of 5 stars">
<img src="star-filled.svg" alt="">
<img src="star-filled.svg" alt="">
<img src="star-filled.svg" alt="">
<img src="star-filled.svg" alt="">
<img src="star-empty.svg" alt="">
</div>
<!-- Image collection -->
<figure role="group" aria-label="Product views">
<img src="front.jpg" alt="Blue dress - front view">
<img src="back.jpg" alt="Blue dress - back view">
<img src="detail.jpg" alt="Blue dress - fabric detail">
</figure>
7. Image Maps
Clickable regions within an image:
<img
src="office-floor-plan.png"
alt="Office floor plan with clickable departments"
usemap="#floor-map"
>
<map name="floor-map">
<area
shape="rect"
coords="0,0,100,100"
href="/sales"
alt="Sales Department"
>
<area
shape="rect"
coords="100,0,200,100"
href="/engineering"
alt="Engineering Department"
>
<area
shape="rect"
coords="200,0,300,100"
href="/hr"
alt="Human Resources"
>
</map>
Framework-Specific Implementation
React/Next.js
// Standard image with alt
function ProductImage({ product }) {
return (
<img
src={product.imageUrl}
alt={`${product.name} - ${product.color} ${product.category}`}
/>
);
}
// Next.js Image component
import Image from 'next/image';
function HeroImage() {
return (
<Image
src="/hero.jpg"
alt="Team collaborating on a design project"
width={1200}
height={600}
priority
/>
);
}
// Decorative image in React
function DecorativeDivider() {
return (
<img
src="/divider.svg"
alt=""
role="presentation"
aria-hidden="true"
/>
);
}
Vue.js
<template>
<!-- Informative image -->
<img
:src="product.image"
:alt="`${product.name} - ${product.description}`"
/>
<!-- Decorative image -->
<img
src="/decorative.svg"
alt=""
aria-hidden="true"
/>
<!-- Complex image with description -->
<figure>
<img
:src="chart.src"
:alt="chart.briefDescription"
:aria-describedby="`chart-desc-${chart.id}`"
/>
<figcaption :id="`chart-desc-${chart.id}`">
{{ chart.longDescription }}
</figcaption>
</figure>
</template>
SVG Accessibility
<!-- Decorative SVG -->
<svg aria-hidden="true" focusable="false">
<!-- ... -->
</svg>
<!-- Informative SVG -->
<svg role="img" aria-labelledby="svg-title svg-desc">
<title id="svg-title">User Statistics</title>
<desc id="svg-desc">Bar chart showing user growth over 12 months</desc>
<!-- ... -->
</svg>
<!-- Interactive SVG -->
<svg role="img" aria-label="Navigation menu">
<!-- ... -->
</svg>
Testing Alt Text
Automated Testing
// Cypress with axe-core
describe('Image Accessibility', () => {
it('should have proper alt text on all images', () => {
cy.visit('/');
cy.injectAxe();
cy.checkA11y(null, {
rules: {
'image-alt': { enabled: true },
'input-image-alt': { enabled: true },
'area-alt': { enabled: true }
}
});
});
});
// Jest with jest-axe
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
test('images have alt text', async () => {
const html = render(<ProductPage />);
const results = await axe(html.container);
expect(results).toHaveNoViolations();
});
Manual Testing Checklist
## Alt Text Audit Checklist
### For Each Image:
- [ ] Has alt attribute (never missing)
- [ ] Alt text describes purpose, not appearance
- [ ] Alt is concise (under 125 characters when possible)
- [ ] Decorative images use alt=""
- [ ] Linked images describe destination
- [ ] Complex images have long descriptions
### Page-Level Checks:
- [ ] Disable images - is content understandable?
- [ ] Screen reader test - do images make sense?
- [ ] No duplicate alt text on different images
- [ ] No images of text (use real text instead)
Screen Reader Testing Commands
VoiceOver (macOS):
- VO + Command + I → List all images on page
- VO + Right Arrow → Navigate to next element
NVDA (Windows):
- G → Jump to next graphic
- Shift + G → Jump to previous graphic
- NVDA + F7 → Elements list (select Images)
JAWS (Windows):
- G → Jump to next graphic
- Shift + G → Jump to previous graphic
- Insert + F7 → Graphics list
CMS and Platform Considerations
WordPress
// Force alt text requirement
add_filter('attachment_fields_to_edit', function($fields, $post) {
$fields['alt_text_required'] = array(
'label' => 'Alt Text (Required)',
'input' => 'text',
'value' => get_post_meta($post->ID, '_wp_attachment_image_alt', true),
'helps' => 'Describe this image for accessibility'
);
return $fields;
}, 10, 2);
Shopify
{% comment %} Product image with dynamic alt {% endcomment %}
<img
src="{{ product.featured_image | img_url: 'large' }}"
alt="{{ product.featured_image.alt | default: product.title }}"
loading="lazy"
>
Common Patterns
E-commerce Product Images
<!-- Main product image -->
<img
src="product-main.jpg"
alt="Blue denim jacket, front view, sizes XS-XXL"
>
<!-- Thumbnail gallery -->
<div role="group" aria-label="Product image gallery">
<button aria-pressed="true">
<img src="thumb-1.jpg" alt="Front view">
</button>
<button aria-pressed="false">
<img src="thumb-2.jpg" alt="Back view">
</button>
<button aria-pressed="false">
<img src="thumb-3.jpg" alt="Side view showing pockets">
</button>
</div>
User Avatars
<!-- With user name -->
<img
src="avatar.jpg"
alt=""
aria-hidden="true"
>
<span>John Smith</span>
<!-- Standalone avatar -->
<img
src="avatar.jpg"
alt="John Smith's profile photo"
>
Icons with Text
<!-- Icon + visible text (icon is decorative) -->
<button>
<img src="save-icon.svg" alt="" aria-hidden="true">
<span>Save Document</span>
</button>
<!-- Icon only (icon is functional) -->
<button aria-label="Save document">
<img src="save-icon.svg" alt="">
</button>
Quality Guidelines
Alt Text Length
| Context | Recommended Length | Example |
|---|---|---|
| Simple image | 10-50 characters | “Red warning icon” |
| Product photo | 50-100 characters | “Blue wireless headphones with noise cancellation” |
| Complex chart | Brief alt + longer description | “Sales chart - see table below for data” |
| Decorative | 0 characters | alt=“” |
Writing Quality Alt Text
Good Examples:
<img alt="Graph showing 150% revenue increase from January to December 2024">
<img alt="Dr. Sarah Chen presenting at the annual tech conference">
<img alt="Step 3: Click the blue Submit button in the top right corner">
Bad Examples:
<img alt="graph"> <!-- Too vague -->
<img alt="image"> <!-- Meaningless -->
<img alt="photo of person"> <!-- Who? Doing what? -->
<img alt="IMG_2847.jpg"> <!-- Filename, not description -->
Related Articles
- WCAG Compliance Hub - Full accessibility guide
- Image SEO Explained - Images for search optimization
References
- W3C - WCAG 2.2 SC 1.1.1 Non-text Content
- W3C - WAI Images Tutorial
- WebAIM - Alternative Text
- MDN - Images in HTML
- W3C - ARIA Images Pattern
- Deque - Image Accessibility