All rules

Sheath rule

a11y-anchor-content

Anchor elements must have accessible content (text, aria-label, or aria-labelledby).
Package
Core
Default severity
error by default
Auto-fix
Manual fix

#Why

Links without accessible content are unusable for screen reader users who navigate by links. Screen readers announce links to help users understand navigation options, but empty links provide no information about where they lead.

#Examples

#Bad

<!-- Empty anchor -->
<a href="/profile"></a>
<!-- Icon-only link without accessible name -->
<a href="/delete"><i class="icon-trash"></i></a>
<!-- Whitespace-only content -->
<a href="/home"> </a>
<!-- Image without alt inside anchor -->
<a href="/gallery"><img src="photo.jpg"></a>

#Good

<!-- Text content -->
<a href="/profile">View Profile</a>
<!-- Icon with aria-label -->
<a href="/delete" aria-label="Delete item"><i class="icon-trash"></i></a>
<!-- A child SVG may contribute the name -->
<a href="/home"><svg aria-label="Home"></svg></a>
<!-- Using aria-labelledby -->
<span id="help-text">Get Help</span>
<a href="/help" aria-labelledby="help-text">?</a>
<!-- Image with alt text -->
<a href="/gallery"><img src="photo.jpg" alt="Photo Gallery"></a>
<!-- Using title attribute -->
<a href="/settings" title="Open Settings"><i class="icon-cog"></i></a>

#Notes

  • Hidden, inert, and non-rendered descendant text does not provide accessible content; explicitly referenced aria-labelledby text remains usable.
  • Visible text serves everyone, not only screen reader users
  • Use aria-label for icon-only links
  • The accessible name should describe the link destination or action
  • Images inside links should have meaningful alt text
  • Opaque attribute spreads such as {{ $attributes }} make the final name unknowable and are not checked. Every explicit branch that produces an exposed link with href must have a name
  • An anchor with a non-empty Alpine x-text or x-html expression, or Livewire wire:text expression (<a href="#" wire:text="label"></a>), is treated as having content because client-side code fills the empty body before the user interacts with it. Bare, empty, and whitespace-only expressions do not count

#References

#Related Rules