wcag-2.2
WCAG 2.2 accessibility guidelines with actionable implementation rules for web developers. Covers contrast ratios, keyboard navigation, focus management, ARIA, screen readers, alt text, touch targets, form validation, color blindness, reduced motion, semantic HTML, and landmarks. Apply whenever writing HTML/CSS/JS, building forms, handling focus, choosing colors for accessibility, implementing interactive components, or reviewing code for a11y compliance. Includes all Level A + AA criteria and new 2.2 additions (focus not obscured, dragging alternatives, target size minimum, redundant entry, accessible authentication, consistent help).
What this skill does
# WCAG 2.2 — Accessibility Guidelines for Developers
## Quick Reference: Contrast Ratios
| Element | Minimum ratio | Rule |
|---------|--------------|------|
| Normal text (<18px / <14px bold) | **4.5:1** | 1.4.3 AA |
| Large text (>=18px / >=14px bold) | **3:1** | 1.4.3 AA |
| UI components & graphical objects | **3:1** | 1.4.11 AA |
| Enhanced (AAA) normal text | **7:1** | 1.4.6 AAA |
| Enhanced (AAA) large text | **4.5:1** | 1.4.6 AAA |
| Focus indicator vs adjacent | **3:1** | 2.4.13 AAA |
## Quick Reference: Target Sizes
| Level | Minimum | Rule |
|-------|---------|------|
| AA | **24x24 CSS px** (or adequate spacing) | 2.5.8 NEW |
| AAA | **44x44 CSS px** | 2.5.5 |
---
## 1. Perceivable
### Images & Non-text Content (1.1.1 A)
- Every `<img>` needs `alt` text. Decorative images: `alt=""`
- Informative images: describe the content, not the appearance
- Complex images (charts, diagrams): provide long description nearby or via `aria-describedby`
- Icon buttons: `aria-label` on the button, `aria-hidden="true"` on the icon
- `<svg>`: use `role="img"` + `aria-label` or `<title>` inside
```html
<!-- Informative -->
<img src="chart.png" alt="Sales increased 40% in Q3 2024">
<!-- Decorative -->
<img src="divider.svg" alt="" role="presentation">
<!-- Icon button -->
<button aria-label="Close dialog">
<svg aria-hidden="true">...</svg>
</button>
```
### Video & Audio (1.2.x A/AA)
- Prerecorded video: provide captions (1.2.2 A) and audio descriptions (1.2.3 A)
- Audio-only: provide text transcript (1.2.1 A)
- Live video: provide live captions (1.2.4 AA)
### Semantic Structure (1.3.1 A)
- Use semantic HTML: `<nav>`, `<main>`, `<aside>`, `<header>`, `<footer>`, `<section>`
- Heading hierarchy: one `<h1>`, don't skip levels (h1 -> h3)
- Lists: `<ul>/<ol>/<dl>`, not `<div>` with bullets
- Tables: `<th scope="col/row">`, `<caption>`, never for layout
- Forms: `<label for="id">`, `<fieldset>/<legend>` for groups
```html
<form>
<fieldset>
<legend>Shipping Address</legend>
<label for="street">Street</label>
<input id="street" type="text" autocomplete="street-address">
</fieldset>
</form>
```
### Reading Order (1.3.2 A)
- DOM order must match visual order
- Don't use CSS (`order`, `flex-direction: row-reverse`) to reorder visually if it breaks reading sequence
- Test: disable CSS and check if content still makes sense
### Sensory Characteristics (1.3.3 A)
- Never rely solely on color, shape, size, or position to convey meaning
- "Click the red button" -> "Click the Delete button (red)"
- "See the chart on the right" -> "See the Sales Chart (Figure 3)"
### Orientation (1.3.4 AA)
- Don't lock content to portrait or landscape
- `@media (orientation: portrait)` is fine for styling, but don't hide content
### Input Purpose (1.3.5 AA)
- Use `autocomplete` attributes on form fields that collect personal data
```html
<input type="text" autocomplete="given-name">
<input type="email" autocomplete="email">
<input type="tel" autocomplete="tel">
<input type="text" autocomplete="street-address">
<input type="text" autocomplete="postal-code">
<input type="text" autocomplete="cc-number">
```
### Color Alone (1.4.1 A)
- Never use color as the only way to convey information
- Error states: red border + icon + text message
- Links in paragraphs: underline or 3:1 contrast to surrounding text + underline on hover/focus
- Charts: use patterns/shapes in addition to colors
- Status indicators: color + icon + text label
```css
/* Bad: only color */
.error { color: red; }
/* Good: color + icon + text */
.error {
color: #CF1124;
border-left: 4px solid #CF1124;
}
.error::before { content: "⚠ "; }
```
### Contrast (1.4.3 AA, 1.4.11 AA)
- **Text**: 4.5:1 minimum (3:1 for large text >=18px or >=14px bold)
- **UI components**: 3:1 for borders, icons, focus indicators, form controls against adjacent colors
- **Disabled elements**: exempt from contrast requirements
- **Placeholder text**: must meet 4.5:1 if it conveys information
```css
/* Meets 4.5:1 on white */
color: #595959; /* 7:1 — safe */
color: #767676; /* 4.54:1 — minimum for normal text */
/* Meets 3:1 on white for UI components */
border-color: #949494; /* 3.03:1 */
```
### Resize (1.4.4 AA)
- Text must be resizable to 200% without loss of content
- Use `rem`/`em` for font sizes, not `px`
- Don't use `max-height` with `overflow: hidden` on text containers
- Test: browser zoom to 200%
### Reflow (1.4.10 AA)
- No horizontal scrolling at 320px viewport width (vertical content)
- No vertical scrolling at 256px viewport height (horizontal content)
- Exceptions: data tables, maps, diagrams, toolbars
- Test: set viewport to 1280px and zoom to 400%
```css
/* Good: responsive container */
.container { max-width: 100%; overflow-wrap: break-word; }
/* Bad: fixed width forcing scroll */
.container { width: 1200px; }
```
### Text Spacing (1.4.12 AA)
- No content loss when users override:
- Line height: 1.5x font size
- Paragraph spacing: 2x font size
- Letter spacing: 0.12x font size
- Word spacing: 0.16x font size
- Don't set fixed heights on containers with text
- Test with browser extension or custom CSS:
```css
* {
line-height: 1.5em !important;
letter-spacing: 0.12em !important;
word-spacing: 0.16em !important;
}
p { margin-bottom: 2em !important; }
```
### Hover/Focus Content (1.4.13 AA)
- Tooltips, popovers triggered by hover/focus must be:
1. **Dismissible**: Esc key closes without moving focus
2. **Hoverable**: user can move pointer over the new content without it disappearing
3. **Persistent**: stays visible until user dismisses, moves focus, or info becomes invalid
```css
/* Good: hoverable tooltip */
.tooltip-trigger:hover + .tooltip,
.tooltip-trigger:focus + .tooltip,
.tooltip:hover {
display: block;
}
```
---
## 2. Operable
### Keyboard Access (2.1.1 A, 2.1.2 A)
- All interactive elements must be keyboard-operable
- Use native elements: `<button>`, `<a href>`, `<input>`, `<select>`
- Custom widgets: add `tabindex="0"` + keyboard event handlers
- No keyboard traps: user must always be able to Tab away
- `tabindex="-1"`: focusable via JS only (e.g., modal containers)
- `tabindex="0"`: in natural tab order
- Never use `tabindex` > 0
```html
<!-- Bad: div with click handler only -->
<div onclick="doThing()">Click me</div>
<!-- Good: button -->
<button onclick="doThing()">Click me</button>
<!-- Good: custom widget with keyboard support -->
<div role="button" tabindex="0"
onclick="doThing()"
onkeydown="if(event.key==='Enter'||event.key===' ')doThing()">
Click me
</div>
```
### Character Key Shortcuts (2.1.4 A)
- If using single-character shortcuts (e.g., "s" to search): allow users to remap or disable them
- Better: require modifier key (Ctrl+S, not just S)
### Timing (2.2.1 A, 2.2.2 A)
- Session timeouts: warn 20+ seconds before, allow 10+ extensions
- Auto-moving content (carousels, tickers): provide pause/stop button
- Auto-refreshing: allow users to control update frequency
### Flashing Content (2.3.1 A)
- Nothing flashes more than 3 times per second
- Avoid flashing entirely when possible
### Skip Navigation (2.4.1 A)
- Provide "Skip to main content" link as first focusable element
```html
<body>
<a href="#main" class="skip-link">Skip to main content</a>
<nav>...</nav>
<main id="main">...</main>
</body>
```
```css
.skip-link {
position: absolute;
top: -40px;
left: 0;
padding: 8px 16px;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
```
### Page Titles (2.4.2 A)
- Every page needs a unique, descriptive `<title>`
- Pattern: "Page Name — Site Name" or "Page Name | Site Name"
### Focus Order (2.4.3 A)
- Tab order must follow logical reading order
- Modals: trap focus inside until dismissed
- Dynamic content: manage focus when content appears/disappears
### Link Purpose (2.4.4 A)
- Link text must make sense in context
- Avoid "click here", "read more", "learn more" without context
- Use `aria-label` or `aria-describedby` whRelated in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.