Good accessibility starts in the design phase, not after handoff. This section covers the visual decisions that determine whether your product works for everyone - from focus rings to touch targets to motion. No code required.
Focus Indicators
When a user navigates with a keyboard or switch device, they rely on a visible focus ring to know which element is active. Many designs suppress the browser default without replacing it - leaving keyboard users with no visual cue at all.
The WCAG Requirements
WCAG 2.4.7 (Level AA)
Focus indicators must be visible
WCAG 2.4.11 (Level AA, WCAG 2.2)
Focus appearance - minimum 2px outline, 3:1 contrast ratio against adjacent colors
WCAG 2.4.12 (Level AAA, WCAG 2.2)
Enhanced focus appearance
See the difference
Tab through each button below. Example 1 is intentionally broken to show what keyboard users experience when focus styles are removed.
Example 1
Result: Fails WCAG 2.4.7
No focus ring - keyboard users are lost
Tab here to see focus disappear (intentional bad pattern).
Example 2
Result: Passes but not recommended
Browser default - visible but inconsistent across browsers
Tab here to see the browser default outline.
Example 3
Result: Passes WCAG 2.4.7 and 2.4.11
Custom focus ring - consistent, high contrast, on-brand
Tab here to see a 2px brand-color ring with offset.
→ What to hand off to your developer
Minimum focus ring spec:
outline: 2px solid [your brand color]
outline-offset: 2px
Contrast ratio: at least 3:1 against adjacent background
Tap targets that are too small cause errors - especially for users with motor impairments, tremors, or arthritis. A target that looks fine on a desktop mockup can be nearly impossible to hit accurately on a phone.
The WCAG Requirements
WCAG 2.5.5 (Level AAA)
Touch targets must be at least 44x44 CSS pixels
WCAG 2.5.8 (Level AA, WCAG 2.2)
Touch targets must be at least 24x24 CSS pixels, OR have sufficient spacing so the total activation area reaches 24x24
WCAG 2.5.8 is the AA requirement. Design to 44x44px minimum to meet AAA and give users the most comfortable experience.
See the difference
Click each square to feel the size difference. Tab to each target to confirm focus is visible on all three.
16 × 16 px
Click the square to try it
Target 1
Result: Fails WCAG 2.5.8
16x16px - common for icon buttons. Fails both 2.5.5 and 2.5.8
24 × 24 px
Click the square to try it
Target 2
Result: Passes WCAG 2.5.8 (AA)
24x24px - minimum AA requirement under WCAG 2.2
44 × 44 px
Click the square to try it
Target 3
Result: Passes WCAG 2.5.5 (AAA)
44x44px - recommended minimum. Passes AAA
→ What to hand off to your developer
Minimum sizes:
Icon buttons: 44x44px touch target (even if the icon is smaller)
Text links inline: ensure 24px line height minimum
Form inputs: 44px height minimum
How to achieve this without making everything huge:
Use padding to extend the clickable area beyond the visible element. Example: a 16x16px icon can have 14px padding on all sides = 44x44px tap area.
In Figma:
Create a 44x44px transparent hit area layer on top of small icon buttons. Label it “Touch target” in your handoff notes.
Color Contrast
Low contrast text is one of the most common WCAG failures - and one of the easiest to prevent at the design stage. It affects users with low vision, users in bright sunlight, and anyone on a lower-quality screen.
The WCAG Requirements
WCAG 1.4.3 (Level AA)
Normal text must have 4.5:1 contrast ratio against background
WCAG 1.4.3 (Level AA)
Large text (18px+ regular or 14px+ bold) needs 3:1
WCAG 1.4.11 (Level AA)
UI components and icons need 3:1 against adjacent colors
WCAG 1.4.6 (Level AAA)
Enhanced contrast - 7:1 for normal text, 4.5:1 for large text
Text contrast examples
Example 1
Result: 2.5:1 - Fails 1.4.3
#9CA3AF on #FFFFFF: 2.54:1
This label just barely passes
Example 2
Result: 4.6:1 - Technically passes, but risky
#6B7280 on #FFFFFF: 4.83:1
This label passes comfortably
Example 3
Result: 10:1 - Passes AA and AAA
#374151 on #FFFFFF: 10.31:1
Example 4: UI component (icon/border)
Result: 1.6:1 - Input border fails WCAG 1.4.11
#D1D5DB on #FFFFFF: 1.47:1
Result: 4.6:1 - Input border passes WCAG 1.4.11
#6B7280 on #FFFFFF: 4.83:1
Quick contrast check
Pick text and background colors to see the WCAG contrast ratio and pass/fail results update live.
Preview text
4.83:1contrast ratio
AA normal text (4.5:1)Result: Pass
AA large text (3:1)Result: Pass
UI components (3:1)Result: Pass
→ What to hand off to your developer
Check every text/background color pair in your design for:
Body text: 4.5:1 minimum
Headings (18px+ or 14px+ bold): 3:1 minimum
Placeholder text: 4.5:1 (it is real text, not decoration)
Disabled states: exempt from contrast requirements
Logos and decorative elements: exempt
Tools to use in Figma:
Figma's built-in contrast checker (Inspect panel)
Stark plugin (free tier checks individual elements)
Colour Contrast Analyser by TPGi (desktop app, free)
Spacing and Readability
Tight spacing makes content harder to read for everyone - and for users with dyslexia, low vision, or cognitive disabilities, it can make a page unusable. WCAG 1.4.12 requires that users can override spacing without content breaking.
The WCAG Requirements
WCAG 1.4.12 (Level AA)
Text spacing - content must not be lost when these are overridden: line height 1.5x font size, letter spacing 0.12x font size, word spacing 0.16x font size, paragraph spacing 2x font size
WCAG 1.4.8 (Level AAA)
Line width no more than 80 characters, line spacing at least 1.5x, paragraph spacing at least 1.5x line spacing
1.4.12 is the AA requirement you must meet. Design to these values by default and your layouts will naturally pass.
See the difference
Use the toggle to compare cramped and comfortable spacing on the same paragraph. Tab to the button and press Enter or Space to switch.
Accessible typography gives readers room to breathe. When line height, letter spacing, and line length work together, people can follow text without losing their place. Dense layouts may look efficient in a mockup, but they increase fatigue for users with dyslexia, low vision, or cognitive disabilities. Generous defaults help everyone read faster with less effort.
Showing: cramped version
Result: Does not meet recommended spacing
Cramped spacing: harder to track lines, tiring to read
→ What to hand off to your developer
Minimum recommended text defaults:
Line height: 1.5 for body text (1.2 for headings is acceptable)
Letter spacing: 0 to 0.05em for body (avoid negative letter spacing)
Max line length: 60-80 characters (use max-width: 65ch in CSS)
Paragraph spacing: at least as large as line height
What to avoid:
Fixed pixel line heights that break when users zoom
Justified text (creates uneven word spacing)
All-caps body text (reduces readability for dyslexic users)
Color as the Only Differentiator
Using color alone to communicate information is one of the most common design-phase accessibility failures. Approximately 8% of men and 0.5% of women have color vision deficiency - they may not be able to distinguish red from green at all. This affects form errors, chart legends, status indicators, and more.
The WCAG Requirement
WCAG 1.4.1 (Level A)
Color must not be the only means of conveying information, indicating an action, prompting a response, or distinguishing a visual element.
This is a Level A requirement - the baseline. There is no acceptable reason to fail it.
Form error example
Toggle between bad and good error treatment. Tab to the toggle and press Enter or Space to switch.
Showing: bad pattern (color only)
Result: Fails WCAG 1.4.1
Color only - red border and red text. A colorblind user may not notice
Status badge example
Compare color-only status dots with badges that pair color and text labels.
Three status indicators shown as colored circles only, with no text labels.
Version 1: Bad (color only)
Result: Fails WCAG 1.4.1
Status indicators using color only
Active
Pending
Error
Version 2: Good (color + text)
Result: Passes WCAG 1.4.1
Status indicators using color and text
→ What to hand off to your developer
For every place color communicates meaning, add at least one of:
Text label (most reliable)
Icon with accessible label
Pattern or shape difference
Bold or italic weight difference
Common places this is missed:
Form validation (red border alone)
Status badges (green/yellow/red dots)
Chart legends (colored lines without labels)
Required field indicators (red asterisk alone)
Link underlines removed (color is then the only differentiator)
For links specifically:
If you remove the underline, links must have 3:1 contrast against surrounding body text AND a non-color hover/focus indicator.
Animation and Motion
Animation can enhance an experience - but for users with vestibular disorders, epilepsy, or motion sensitivity, it can cause dizziness, nausea, or seizures. The fix is not to remove all animation. It is to give users control.
The WCAG Requirements
WCAG 2.3.1 (Level A)
No content flashes more than 3 times per second
WCAG 2.3.3 (Level AAA)
Animation from interactions can be disabled
Best practice
Respect prefers-reduced-motion OS setting
2.3.1 is Level A - never flash content. prefers-reduced-motion is not required by WCAG AA but is expected by users and strongly recommended.
Live motion example
Choose a motion style below to preview the card.
In real implementations, this switch happens automatically via the prefers-reduced-motion CSS media query - users never need to choose manually. The buttons here are just to show you both experiences.
Designer decision guide
Question to answerFix requiredAction neededYou're done
Legend: blue means a question to answer, red means a fix is required, amber means action needed, teal means you are done.
→ What to hand off to your developer
For every animation in your design, specify:
Full motion version: [describe the animation]
Reduced motion version: [instant appearance, or no animation]
Parallax scrolling without a reduced-motion alternative
Auto-playing carousels without pause controls
Component Specs for Designers
The six principles above apply to every component you design. This section shows what those principles look like in practice: the specific decisions to make and annotate before handoff, grouped by component type. Each one links to the playground pattern your developer will implement.
Forms and Input
Form validation
What to design
Label above every input, never placeholder-only
Error state: red border + warning icon + error text (never color alone)
Required fields marked with an asterisk and a legend explaining it
Error message positioned directly below the field it describes
What to annotate
Tell your developer: which fields are required, what the error messages say, and that errors must be announced to screen readers on submit.
Visible close button in the top-right corner, minimum 44x44px
Dialog title as visible text at the top of the modal
Backdrop should not be the only way to close: provide a button too
Design for keyboard: the first focusable element receives focus on open
What to annotate
Tell your developer: which element receives focus when the modal opens, that Tab must stay inside the modal while it is open, and that Escape must close it and return focus to the trigger.
Used for destructive or irreversible actions only (delete, sign out)
Must have at least two buttons: confirm and cancel
Confirm button should be visually distinct (red for destructive actions)
Title and body text must be visible: no icon-only alerts
What to annotate
Tell your developer: that this is a blocking dialog requiring user response, that focus must go to the cancel button by default (not the destructive action), and that background content must be inert.
Appears on both hover and keyboard focus, not hover only
Text label only: no interactive content inside a tooltip
Stays visible long enough to read (do not dismiss on mouse movement)
Position so it does not cover the element it describes
What to annotate
Tell your developer: the exact tooltip text for every instance, that it must appear on focus not just hover, and that it must not contain links or buttons.
Trigger must look like a button, not a styled div or text link
Show open/closed state visually (chevron that rotates, or +/-)
All states: default, hover, focus, open, disabled
Touch target for each menu item minimum 44px height
What to annotate
Tell your developer: that the trigger must be a real button element, that arrow keys must navigate the options, and that Escape must close the menu and return focus to the trigger.
Skip link as the first element on every page (hidden until focused)
Active page indicated by more than color alone (underline, bold, or shape)
Mobile nav accessible without a mouse (hamburger must be keyboard operable)
Touch targets for all nav items minimum 44x44px
What to annotate
Tell your developer: which page is active on each view, that the skip link must jump to the main content area, and that the mobile menu must trap focus when open.
Current page shown as text, not a link (you are already here)
Separator between items is decorative: do not rely on it for meaning
Show the full path from home to current page
Wrap gracefully on small screens: do not truncate the current page
What to annotate
Tell your developer: that the current page item must be marked aria-current="page" and that the breadcrumb must be wrapped in a nav element with a label.
Active tab uses underline, border, or shape change, not color alone
Enough contrast between selected and unselected tab states (3:1 minimum)
Tab panel content is immediately below the tab row
Touch target for each tab minimum 44px height
What to annotate
Tell your developer: which tab is active by default, that arrow keys must move between tabs, and that Tab must enter the panel content (not move to the next tab).
Trigger must look like a button: include a chevron or +/- indicator
Indicator changes visually when section is open vs closed
Open state uses more than color to show it is expanded
Touch target for each trigger minimum 44px height
What to annotate
Tell your developer: that the trigger must be a real button element, that aria-expanded must update on open/close, and whether multiple sections can be open at once.
Current page indicated by more than color alone (border, bold, or shape)
Previous and Next buttons always visible, disabled when at the boundary
Each page number is a real link or button, not styled text
Touch targets minimum 44x44px for all page controls
What to annotate
Tell your developer: that the current page must be marked aria-current="page", that disabled buttons must still be focusable with a disabled label, and that the pagination must be wrapped in a nav element with a label.
Play/pause button visible and accessible at all times
Previous and Next controls labeled with text, not arrows only
Auto-play off by default, or pauses on hover and focus
Current slide position shown as text ("Slide 2 of 5")
What to annotate
Tell your developer: that auto-play must pause on hover and focus, that each slide must have a heading or label, that controls must be keyboard operable, and that animation must respect prefers-reduced-motion.
Every icon-only button must have a text label specified in the design
Label does not need to be visible but must be in the handoff notes
Touch target minimum 44x44px even when the icon is smaller
Tooltip showing the label appears on hover and focus
What to annotate
Tell your developer: the exact label text for every icon button, that aria-label must match that text exactly, and that the icon itself must be hidden from screen readers.
For every image, specify in handoff: is it informative or decorative?
Informative images: write the alt text in your design notes
Decorative images: mark them explicitly as decorative in notes
Linked images: alt text must describe the destination, not the image
What to annotate
Tell your developer: the exact alt text for every informative image, which images are decorative (alt=""), and that linked images need alt text describing where the link goes.
Check every text/background pair before finalising the design
Body text: 4.5:1 minimum against its background
Large text (18px+ regular or 14px+ bold): 3:1 minimum
UI component borders and icons: 3:1 against adjacent background
What to annotate
Tell your developer: the exact hex values for every color pair used, and flag any combinations that are close to the minimum ratio so they can verify in code.
Always include a text label showing current progress ("Step 2 of 4" or "Loading: 60%"): never a visual bar alone
Color change alone is not enough to show progress
For step indicators, show which step is current and which are complete
Touch targets for any interactive step indicators minimum 44x44px
What to annotate
Tell your developer: that progress must be announced to screen readers as it updates, the exact label format to use, and whether the indicator is a progress bar or a step tracker.
You've seen the principles and the component specs. The playground shows what breaks when these specs are ignored and gives developers the accessible code to fix it.
The playground shows how each of these components maps to real broken and accessible UI. Pick a pattern, see who is affected, and copy the accessible code.