--- name: tailwindcss-accessibility description: Tailwind CSS accessibility patterns including WCAG 2.2 compliance, touch targets, focus management, and ARIA support --- # Tailwind CSS Accessibility Patterns (WCAG 2.2 - 2025/2026) ## WCAG 2.2 Overview (Current Standard) WCAG 2.2 was released October 2023 and is the current W3C standard. Key additions relevant to Tailwind: - **2.5.8 Target Size (Level AA)**: 24x24 CSS pixels minimum, 44x44 recommended - **2.4.11 Focus Not Obscured**: Focus indicators must be visible - **2.4.13 Focus Appearance**: Enhanced focus indicator requirements - **3.3.7 Redundant Entry**: Don't require re-entering information - **3.2.6 Consistent Help**: Help mechanisms in consistent locations ## Focus Management ### Focus Ring Utilities ```html
``` ```css @layer components { .focus-ring { @apply focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-2; } .focus-ring-inset { @apply focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-inset; } } ``` ### Skip Links ```html Skip to main content
Navigation...
Main content
``` ### Focus Trap Pattern ```html ``` ## Screen Reader Utilities ### Visually Hidden Content ```html Additional context for screen readers Skip to main ``` ### Announcing Dynamic Content ```html
3 items added to cart
``` ## Color Contrast ### High Contrast Patterns ```html

4.5:1 contrast ratio

May not meet WCAG AA (3:1 min for large text)

Large text - 3:1 ratio OK

``` ### Dark Mode Contrast ```html

High contrast text

Secondary text with adequate contrast

⚠️ May have contrast issues in dark mode

``` ### Focus Indicator Contrast ```css @theme { /* High contrast focus ring */ --color-focus: oklch(0.55 0.25 250); --color-focus-offset: oklch(1 0 0); } ``` ```html ``` ## Motion and Animation ### Reduced Motion ```html
Bouncing element (static for motion-sensitive users)
Fades in (instant for motion-sensitive)
Scales on hover (shadow only for motion-sensitive)
``` ### Safe Animation Patterns ```css @layer components { /* Animations that respect reduced motion */ .animate-fade-in { @apply animate-in fade-in duration-300; @apply motion-reduce:animate-none motion-reduce:opacity-100; } .animate-slide-up { @apply animate-in slide-in-from-bottom-4 duration-300; @apply motion-reduce:animate-none motion-reduce:translate-y-0; } } ``` ### Pause Animation on Hover ```html
Loading spinner
``` ## Form Accessibility ### Accessible Form Fields ```html

We'll never share your email

Notification preference
``` ### Error States ```html
``` ### Form Validation Feedback ```css /* Style based on aria-invalid attribute */ @custom-variant aria-invalid (&[aria-invalid="true"]); ``` ```html ``` ## Interactive Components ### Accessible Buttons ```html ``` ### Accessible Dropdowns ```html
``` ### Accessible Tabs ```html
Profile content
``` ## Touch Targets (WCAG 2.2 - Critical for 2025/2026) ### WCAG 2.2 Target Size Requirements | Level | Requirement | Tailwind Class | |-------|-------------|----------------| | **AA (2.5.8)** | 24x24 CSS pixels minimum | `min-h-6 min-w-6` | | **Recommended** | 44x44 CSS pixels | `min-h-11 min-w-11` | | **AAA (2.5.5)** | 44x44 CSS pixels | `min-h-11 min-w-11` | | **Optimal** | 48x48 CSS pixels | `min-h-12 min-w-12` | Platform guidelines comparison: - **Apple iOS**: 44x44 points minimum - **Google Android**: 48x48 dp minimum - **Microsoft Fluent**: 44x44 pixels minimum ### Minimum Touch Target Size ```html ``` ### Extend Touch Target Beyond Visible Element ```html Small Link Text

Card Title

Description text

View details
``` ### Spacing Between Interactive Elements WCAG 2.2 requires 24px spacing OR targets must be 24px minimum: ```html
``` ### Touch Target Exceptions (WCAG 2.2) Targets can be smaller than 24x24 if: - Inline text links within sentences - Browser-provided controls (scrollbars) - Size is essential to information - A larger equivalent target exists on same page ## Text Accessibility ### Readable Text ```html

Long form content with comfortable line height

Content with optimal line length (45-75 characters)

Paragraph 1

Paragraph 2

``` ### Text Resizing ```html

Scales with user's font size preferences

⚠️ Won't scale with browser zoom

Content height adjusts with text size
``` ## Semantic HTML with Tailwind ### Landmark Regions ```html

Page Title

Section Title

Content...

``` ### Heading Hierarchy ```html

Main Title (H1)

Section (H2)

Subsection (H3)

Content...

``` ## Testing Accessibility ### Browser DevTools Checklist 1. **Color contrast**: Use contrast checker 2. **Focus order**: Tab through the page 3. **Zoom**: Test at 200% zoom 4. **Reduced motion**: Enable in OS settings ### Automated Testing ```javascript // axe-core integration import { axe, toHaveNoViolations } from 'jest-axe'; expect.extend(toHaveNoViolations); test('component is accessible', async () => { const { container } = render(); const results = await axe(container); expect(results).toHaveNoViolations(); }); ``` ## Best Practices Summary (WCAG 2.2 - 2025/2026) | Pattern | Implementation | WCAG Level | |---------|---------------|------------| | Focus visible | `focus-visible:ring-2 focus-visible:ring-offset-2` | 2.4.7 (AA) | | Screen reader only | `sr-only` | 1.3.1 (A) | | Skip links | `sr-only focus:not-sr-only focus:absolute` | 2.4.1 (A) | | Reduced motion | `motion-reduce:animate-none motion-reduce:transition-none` | 2.3.3 (AAA) | | Touch targets (min) | `min-h-6 min-w-6` (24px) | 2.5.8 (AA) | | Touch targets (rec) | `min-h-11 min-w-11` (44px) | 2.5.5 (AAA) | | Touch spacing | `gap-3` (12px minimum between targets) | 2.5.8 (AA) | | Text contrast | 4.5:1 for normal, 3:1 for large text | 1.4.3 (AA) | | Form errors | `aria-invalid="true"` + `role="alert"` | 3.3.1 (A) | | Focus not obscured | Avoid `z-index` covering focused elements | 2.4.11 (AA) | ### Quick Reference: Touch-Friendly Component ```html ```