Tailwind CSS Tutorial · Tailwind in Real Projects · Lesson 24 of 27
Accessibility with Tailwind
Accessible Tailwind interfaces: focus styles, screen-reader-only text, colour contrast, motion preferences, and ARIA-based styling.
Checklist
- Keyboard focus: never remove outlines without a replacement. Use
focus-visible:outline-2 focus-visible:outline-offset-2. - Screen-reader text:
sr-onlyhides text visually but keeps it for screen readers (icon buttons!). - Contrast: body text needs 4.5:1.
text-gray-400on white fails;text-gray-600passes. - Motion: wrap animations in
motion-safe:. - ARIA states: style from ARIA attributes so visuals and semantics stay in sync:
aria-expanded:rotate-180,aria-selected:bg-sky-100,aria-disabled:opacity-50. Data attributes work too:data-active:font-bold.
<div class="flex items-center gap-4 p-6">
<button class="rounded-full p-2 text-gray-700 hover:bg-gray-100 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-600">
<svg class="size-6" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 18L18 6M6 6l12 12"/></svg>
<span class="sr-only">Close dialog</span>
</button>
<p class="text-gray-400">gray-400 text: too faint</p>
<p class="text-gray-600">gray-600 text: passes</p>
</div>
<div class="m-6 max-w-sm rounded-lg border">
<button aria-expanded="true" class="group flex w-full items-center justify-between p-4 font-medium">
Shipping details
<span class="transition group-aria-expanded:rotate-180">▾</span>
</button>
<p class="border-t p-4 text-sm text-gray-600">The arrow rotates because the button has aria-expanded="true".</p>
</div>
Test yourself
Which class keeps text available to screen readers but hides it visually?
sr-onlyhiddeninvisibleopacity-0
Show answer
Answer: sr-only
hidden and invisible hide content from assistive technology too.