Concise rules for building accessible, fast, delightful UIs. Use MUST/SHOULD/NEVER to guide decisions.
Interactions
Keyboard
- •MUST: Full keyboard support per WAI-ARIA APG
- •MUST: Visible focus rings (
:focus-visible; group with:focus-within) - •MUST: Manage focus (trap, move, return) per APG patterns
- •NEVER:
outline: nonewithout visible focus replacement
Targets & Input
- •MUST: Hit target ≥24px (mobile ≥44px); if visual <24px, expand hit area
- •MUST: Mobile
<input>font-size ≥16px to prevent iOS zoom - •NEVER: Disable browser zoom (
user-scalable=no,maximum-scale=1) - •MUST:
touch-action: manipulationto prevent double-tap zoom - •SHOULD: Set
-webkit-tap-highlight-colorto match design
Forms
- •MUST: Hydration-safe inputs (no lost focus/value)
- •NEVER: Block paste in
<input>/<textarea> - •MUST: Loading buttons show spinner and keep original label
- •MUST: Enter submits focused input; in
<textarea>, ⌘/Ctrl+Enter submits - •MUST: Keep submit enabled until request starts; then disable with spinner
- •MUST: Accept free text, validate after—don't block typing
- •MUST: Allow incomplete form submission to surface validation
- •MUST: Errors inline next to fields; on submit, focus first error
- •MUST:
autocomplete+ meaningfulname; correcttypeandinputmode - •SHOULD: Disable spellcheck for emails/codes/usernames
- •SHOULD: Placeholders end with
…and show example pattern - •MUST: Warn on unsaved changes before navigation
- •MUST: Compatible with password managers & 2FA; allow pasting codes
- •MUST: Trim values to handle text expansion trailing spaces
- •MUST: No dead zones on checkboxes/radios; label+control share one hit target
State & Navigation
- •MUST: URL reflects state (deep-link filters/tabs/pagination/expanded panels)
- •MUST: Back/Forward restores scroll position
- •MUST: Links use
<a>or<Link>for navigation (support Cmd/Ctrl/middle-click) - •NEVER: Use
<button>or<div>for navigation
Feedback
- •SHOULD: Optimistic UI; reconcile on response; on failure rollback or offer Undo
- •MUST: Confirm destructive actions or provide Undo window
- •MUST: Use polite
aria-livefor toasts/inline validation - •SHOULD: Ellipsis (
…) for options opening follow-ups ("Rename…") and loading states ("Loading…")
Touch & Drag
- •MUST: Generous targets, clear affordances; avoid finicky interactions
- •MUST: Delay first tooltip; subsequent peers instant
- •MUST:
overscroll-behavior: containin modals/drawers - •MUST: During drag, disable text selection and set
inerton dragged elements - •MUST: If it looks clickable, it must be clickable
Autofocus
- •SHOULD: Autofocus on desktop with single primary input; rarely on mobile
Animation
- •MUST: Honor
prefers-reduced-motion(provide reduced variant or disable) - •SHOULD: Prefer CSS > Web Animations API > JS libraries
- •MUST: Animate compositor-friendly props (
transform,opacity) only - •NEVER: Animate layout props (
top,left,width,height) - •NEVER:
transition: all—list properties explicitly - •SHOULD: Animate only to clarify cause/effect or add deliberate delight
- •SHOULD: Choose easing to match the change (size/distance/trigger)
- •MUST: Animations interruptible and input-driven (no autoplay)
- •MUST: Correct
transform-origin(motion starts where it "physically" should) - •MUST: SVG transforms on
<g>wrapper withtransform-box: fill-box
Layout
- •SHOULD: Optical alignment; adjust ±1px when perception beats geometry
- •MUST: Deliberate alignment to grid/baseline/edges—no accidental placement
- •SHOULD: Balance icon/text lockups (weight/size/spacing/color)
- •MUST: Verify mobile, laptop, ultra-wide (simulate ultra-wide at 50% zoom)
- •MUST: Respect safe areas (
env(safe-area-inset-*)) - •MUST: Avoid unwanted scrollbars; fix overflows
- •SHOULD: Flex/grid over JS measurement for layout
Content & Accessibility
- •SHOULD: Inline help first; tooltips last resort
- •MUST: Skeletons mirror final content to avoid layout shift
- •MUST:
<title>matches current context - •MUST: No dead ends; always offer next step/recovery
- •MUST: Design empty/sparse/dense/error states
- •SHOULD: Curly quotes (" "); avoid widows/orphans (
text-wrap: balance) - •MUST:
font-variant-numeric: tabular-numsfor number comparisons - •MUST: Redundant status cues (not color-only); icons have text labels
- •MUST: Accessible names exist even when visuals omit labels
- •MUST: Use
…character (not...) - •MUST:
scroll-margin-topon headings; "Skip to content" link; hierarchical<h1–h6> - •MUST: Resilient to user-generated content (short/avg/very long)
- •MUST: Locale-aware dates/times/numbers (
Intl.DateTimeFormat,Intl.NumberFormat) - •MUST: Accurate
aria-label; decorative elementsaria-hidden - •MUST: Icon-only buttons have descriptive
aria-label - •MUST: Prefer native semantics (
button,a,label,table) before ARIA - •MUST: Non-breaking spaces:
10 MB,⌘ K, brand names
Content Handling
- •MUST: Text containers handle long content (
truncate,line-clamp-*,break-words) - •MUST: Flex children need
min-w-0to allow truncation - •MUST: Handle empty states—no broken UI for empty strings/arrays
Performance
- •SHOULD: Test iOS Low Power Mode and macOS Safari
- •MUST: Measure reliably (disable extensions that skew runtime)
- •MUST: Track and minimize re-renders (React DevTools/React Scan)
- •MUST: Profile with CPU/network throttling
- •MUST: Batch layout reads/writes; avoid reflows/repaints
- •MUST: Mutations (
POST/PATCH/DELETE) target <500ms - •SHOULD: Prefer uncontrolled inputs; controlled inputs cheap per keystroke
- •MUST: Virtualize large lists (>50 items)
- •MUST: Preload above-fold images; lazy-load the rest
- •MUST: Prevent CLS (explicit image dimensions)
- •SHOULD:
<link rel="preconnect">for CDN domains - •SHOULD: Critical fonts:
<link rel="preload">withfont-display: swap
Dark Mode & Theming
- •MUST:
color-scheme: darkon<html>for dark themes - •SHOULD:
<meta name="theme-color">matches page background - •MUST: Native
<select>: explicitbackground-colorandcolor(Windows fix)
Hydration
- •MUST: Inputs with
valueneedonChange(or usedefaultValue) - •SHOULD: Guard date/time rendering against hydration mismatch
Design
- •SHOULD: Layered shadows (ambient + direct)
- •SHOULD: Crisp edges via semi-transparent borders + shadows
- •SHOULD: Nested radii: child ≤ parent; concentric
- •SHOULD: Hue consistency: tint borders/shadows/text toward bg hue
- •MUST: Accessible charts (color-blind-friendly palettes)
- •MUST: Meet contrast—prefer APCA over WCAG 2
- •MUST: Increase contrast on
:hover/:active/:focus - •SHOULD: Match browser UI to bg
- •SHOULD: Avoid dark color gradient banding (use background images when needed)