Accessibility
Icons can be decorative or meaningful — how you mark them up matters for screen reader users.
Decorative Icons
When an icon is purely visual and the surrounding text already conveys the meaning, hide it from screen readers with aria-hidden="true":
<button class="btn">
<i class="trker trker-download" aria-hidden="true"></i>
Download File
</button>
Without aria-hidden, a screen reader might announce "download Download File" — the icon name and the button label both.
Meaningful Icons
When an icon conveys information on its own (no visible label), give it a text alternative using role="img" and aria-label:
<!-- Status indicator -->
<i
class="trker trker-check-circle text-green-500"
role="img"
aria-label="Success"
></i>
Icon-Only Buttons
Buttons with no visible text must have an accessible label. Use aria-label on the button itself:
<button aria-label="Close dialog">
<i class="trker trker-times" aria-hidden="true"></i>
</button>
<button aria-label="Open settings">
<i class="trker trker-settings" aria-hidden="true"></i>
</button>
Alternatively, use a visually hidden span instead of aria-label — this also benefits users who override stylesheets:
<button>
<i class="trker trker-settings" aria-hidden="true"></i>
<span class="sr-only">Open settings</span>
</button>
Icons Inline with Text
When an icon appears next to a visible label, hide the icon and let the label do the work:
<a href="/profile">
<i class="trker trker-user me-1" aria-hidden="true"></i>
My Profile
</a>
Animated Icons
Animations can be distracting for users with vestibular disorders. Respect the prefers-reduced-motion media query:
/* In your CSS */
@media (prefers-reduced-motion: reduce) {
.trker-spin,
.trker-pulse,
.trker-beat,
.trker-bounce,
.trker-shake,
.trker-fade {
animation: none;
}
}