# Icons Have Labels

**MUST** · **ID:** `content-icons-have-labels` · **Category:** content
**Source:** [Vercel](https://github.com/vercel-labs/agent-skills/blob/main/skills/web-design-guidelines/SKILL.md)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/content-icons-have-labels

> MUST: Icon-only buttons have descriptive `aria-label`

Convey the same meaning with text for non-sighted users

Icons aren't universally understood and are invisible to screen readers. Either show a visible text label alongside the icon, or provide an aria-label for icon-only buttons. The label should describe the action, not the icon itself.

## Bad — do not do this

`content-icons-have-labels-bad`

```tsx
import { Edit, Trash2, Share2 } from 'lucide-react';
import { ScreenReaderView } from '@/components/demo-kit/ScreenReaderView';

export function IconsHaveLabelsBad() {
  return (
    <div className="w-full max-w-sm">
      <ScreenReaderView>
      <div className="flex gap-2">
        <button className="p-2 bg-muted rounded hover:bg-muted">
          <Edit className="w-5 h-5 text-foreground" />
        </button>
        <button className="p-2 bg-muted rounded hover:bg-muted">
          <Trash2 className="w-5 h-5 text-foreground" />
        </button>
        <button className="p-2 bg-muted rounded hover:bg-muted">
          <Share2 className="w-5 h-5 text-foreground" />
        </button>
      </div>
      </ScreenReaderView>
      <p className="text-xs text-error mt-4">
        Icon-only buttons have no accessible labels
      </p>
    </div>
  );
}
```

## Good — do this

`content-icons-have-labels-good`

```tsx
import { Edit, Trash2, Share2 } from 'lucide-react';
import { ScreenReaderView } from '@/components/demo-kit/ScreenReaderView';

export function IconsHaveLabelsGood() {
  return (
    <div className="w-full max-w-sm">
      <ScreenReaderView>
      <div className="flex gap-2">
        <button
          className="p-2 bg-muted rounded hover:bg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
          aria-label="Edit item"
        >
          <Edit className="w-5 h-5 text-foreground" />
        </button>
        <button
          className="p-2 bg-muted rounded hover:bg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
          aria-label="Delete item"
        >
          <Trash2 className="w-5 h-5 text-foreground" />
        </button>
        <button
          className="p-2 bg-muted rounded hover:bg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
          aria-label="Share item"
        >
          <Share2 className="w-5 h-5 text-foreground" />
        </button>
      </div>
      </ScreenReaderView>
      <p className="text-xs text-success mt-4">
        Descriptive aria-labels for screen readers
      </p>
    </div>
  );
}
```

## References

- [Accessible Icon Buttons](https://www.sarasoueidan.com/blog/accessible-icon-buttons/)
