# All icons and SVG graphics have meaningful text alternatives via aria-label, title, or nested text

- **Pattern:** `ab-001610` (`gov-section-508.forms-interactive.icon-labels`)
- **Severity:** info
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001610
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001610)

## Why it matters

Icon-only buttons and SVG graphics convey meaning entirely through visual shape—a trash can means delete, a gear means settings, an X means close. Without a text alternative, screen readers announce only "button" or the SVG element name, leaving users with no indication of the action they are about to take. WCAG 2.2 SC 1.1.1 (Level A) requires all non-text content to have a text alternative; SC 4.1.2 (Level A) requires that UI components expose name, role, and value to AT. Section 508 2018 Refresh 502.3.1 mirrors this. Toolbar rows of unlabeled icon buttons are one of the most common Section 508 failure patterns in web applications.

## Severity rationale

Info because icon labeling failures affect specific interactive controls rather than global navigation, and users may sometimes infer intent from context or position—but the failure is still a Level A WCAG violation.

## Remediation

Add accessible labels to every icon used as a control or to convey information. Use `aria-label` on the button, or `aria-hidden="true"` on the icon with a visually hidden text sibling:
```tsx
{/* Method 1: aria-label on the button */}
<button aria-label="Delete record">
  <TrashIcon aria-hidden="true" />
</button>

{/* Method 2: visually hidden text (preferred for complex icons) */}
<button>
  <GearIcon aria-hidden="true" />
  <span className="sr-only">Settings</span>
</button>

{/* Method 3: SVG title element */}
<svg role="img" aria-labelledby="icon-title">
  <title id="icon-title">Download file</title>
  <path d="..." />
</svg>
```
Add `sr-only` to `globals.css` if not already present:
```css
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
```

## Detection

- **ID:** `icon-labels`
- **Severity:** `info`
- **What to look for:** Count all relevant instances and enumerate each. Find all icon elements (`<svg>`, icon fonts, icon components) and images used as icons. Check whether each has a text alternative: `aria-label`, `<title>` element (SVG), or nested text.
- **Pass criteria:** All icons have meaningful text alternatives. At least 1 implementation must be verified. Icon-only buttons or links have `aria-label` or `aria-describedby`. SVG icons have a nested `<title>` element or `aria-label`.
- **Fail criteria:** Icons are used without any text alternative, making their purpose unclear to screen readers.
- **Skip (N/A) when:** No icons are used, or icons are purely decorative with text alternatives elsewhere on the element.
- **Detail on fail:** Example: `"7 icon-only buttons in the toolbar: heart icon (add to favorites), share icon, download icon, print icon, settings icon, help icon, and close button. None have aria-label or title attributes. Screen reader users cannot determine their purpose."`
- **Remediation:** Add labels to icons:
  ```tsx
  // SVG with title
  <svg aria-label="Add to favorites">
    <title>Add to favorites</title>
    <path d="..." />
  </svg>

  // Icon with aria-label
  <button aria-label="Download file">
    <DownloadIcon />
  </button>

  // Icon with nested text (hidden visually)
  <button>
    <HeartIcon />
    <span className="sr-only">Add to favorites</span>
  </button>
  ```

## External references

- wcag 1.1.1
- wcag 4.1.2
- section-508 502.3.1

Taxons: accessibility

HTML version: https://auditbuffet.com/patterns/ab-001610
