Web Interface Design Guidelines
Comprehensive code review for web interface compliance with industry standards including WCAG 2.2, Core Web Vitals, and modern UX best practices.
How to Use
- •Read the specified files (or prompt user for files/pattern)
- •Check against all rules below
- •Output findings in terse
file:lineformat - •Group by file, state issue + location, skip explanations unless fix is non-obvious
1. Accessibility (WCAG 2.2 Compliance)
1.1 Semantic HTML (First Rule)
"If you can use a native HTML element with built-in semantics, use it instead of ARIA."
- •Use
<button>for actions,<a>/<Link>for navigation (NEVER<div onClick>or<span onClick>) - •Use semantic containers:
<header>,<main>,<nav>,<footer>,<aside>,<section>,<article> - •Use heading hierarchy
<h1>–<h6>in logical order (no skipping levels) - •Use
<label>withfor/htmlForfor form controls - •Use
<table>for tabular data (not CSS grids for data tables) - •Use
<ul>/<ol>for lists - •Include skip link to main content:
<a href="#main">Skip to content</a>
1.2 ARIA Usage
"No ARIA is better than bad ARIA" – Sites with ARIA average 41% more errors than those without.
- •Only use ARIA when no native HTML equivalent exists (custom widgets like tabs, trees, comboboxes)
- •Icon-only buttons MUST have
aria-label:<button aria-label="Close"> - •Decorative icons MUST have
aria-hidden="true" - •Async updates (toasts, validation) MUST use
aria-live="polite"(reserveassertivefor critical errors) - •Collapsed sections need
aria-expanded="false", expanded needaria-expanded="true" - •Hidden elements need
aria-hidden="true"to exclude from screen readers - •Invalid form fields need
aria-invalid="true" - •Required fields need
aria-required="true"or HTMLrequired
1.3 Images & Media
- •All
<img>MUST havealtattribute - •Decorative images:
alt=""(empty, not missing) - •Informative images: descriptive
alttext explaining content/purpose - •Complex images (charts, diagrams): provide long description or
aria-describedby - •Background images with meaning: provide text alternative nearby
- •Video: provide captions and transcripts
- •Audio: provide transcripts
1.4 Color & Contrast
- •Normal text: minimum 4.5:1 contrast ratio
- •Large text (18px+ or 14px+ bold): minimum 3:1 contrast ratio
- •UI components (buttons, inputs, icons): minimum 3:1 contrast ratio
- •NEVER rely solely on color to convey meaning (add icons, text, or patterns)
- •Test with colorblind simulation tools
- •Error states: don't just use red—add icons or text
2. Focus & Keyboard Navigation
2.1 Focus Visibility
- •Interactive elements MUST have visible focus indicator
- •NEVER use
outline: noneoroutline-nonewithout replacement - •Use
:focus-visibleover:focus(avoids focus ring on click) - •Focus indicator minimum: 2px thick, 3:1 contrast against adjacent colors
- •Use
focus-visible:ring-*(Tailwind) or custom focus styles - •Group related controls with
:focus-within
2.2 Keyboard Accessibility
- •ALL interactive elements must be reachable via Tab/Shift+Tab
- •Logical tab order matching visual layout
- •Custom widgets need keyboard handlers:
onKeyDown/onKeyUp - •Modals/dialogs: trap focus inside, return focus on close
- •Collapsible elements: Enter/Space to toggle
- •Escape key should close modals, dropdowns, tooltips
- •Never use
tabindex> 0 (disrupts natural order) - •
tabindex="-1"for programmatically focusable but not tabbable elements - •
tabindex="0"to make non-interactive elements focusable (when ARIA role requires it)
3. Forms
3.1 Labels & Association
- •Every input MUST have a visible
<label>withfor/htmlFormatching inputid - •OR wrap input inside
<label>element - •Placeholder is NOT a substitute for label
- •Group related inputs with
<fieldset>and<legend> - •Checkboxes/radios: label + control share single hit target (no dead zones)
3.2 Input Attributes
- •Use correct
type:email,tel,url,number,password,search,date - •Use
inputmodefor mobile keyboards:numeric,tel,email,url,decimal - •Use meaningful
nameattributes - •Use
autocompletefor common fields:name,email,tel,street-address,postal-code,cc-number - •Use
autocomplete="off"on non-auth fields to avoid password manager triggers - •Disable
spellCheckon emails, codes, usernames:spellCheck={false}
3.3 Validation & Error Handling
- •NEVER block paste: no
onPaste+preventDefault() - •Show inline errors next to the field, not just at form top
- •Focus first error on submit
- •Use
aria-invalid="true"andaria-describedbyfor error messages - •Submit button stays enabled until request starts; show spinner during request
- •Warn before navigation with unsaved changes (
beforeunloador router guard)
3.4 Placeholders
- •Placeholders should show example format, not instructions
- •End with ellipsis:
"Search…","e.g., john@example.com" - •Placeholder contrast: minimum 4.5:1 (don't use light gray)
4. Animation & Motion
4.1 Reduced Motion (REQUIRED)
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
- •Honor
prefers-reduced-motionmedia query - •Provide reduced alternative (fade instead of slide) or disable animation
- •Test: Windows Settings → Accessibility → Animation effects OFF
- •Test: Mac System Settings → Accessibility → Display → Reduce motion ON
4.2 Performance-Safe Animations
- •ONLY animate
transformandopacity(GPU-accelerated, no reflows) - •NEVER animate:
width,height,top,left,margin,padding,font-size - •NEVER use
transition: all— list properties explicitly:transition: transform 200ms, opacity 200ms - •Set correct
transform-origin - •SVG transforms: use
<g>wrapper withtransform-box: fill-box; transform-origin: center
4.3 Timing Guidelines
- •Micro-interactions (buttons, hovers): 100-200ms
- •Small UI changes (tooltips, dropdowns): 200-300ms
- •Medium transitions (modals, panels): 300-500ms
- •Large movements (page transitions): 500-800ms
- •Anything over 1 second feels slow
- •Animations should be interruptible — respond to user input mid-animation
5. Typography
5.1 Font Sizes
- •Body text: minimum 16px (1rem)
- •Mobile: 14-16px minimum
- •Use relative units:
rem,em,%(notpxon root<html>) - •Allow text to scale to 200% without loss of content (WCAG requirement)
5.2 Line Height & Length
- •Body text:
line-height: 1.5minimum (WCAG AA) - •Headings:
line-height: 1.2-1.35 - •Optimal line length: 50-75 characters (66 is sweet spot)
- •Mobile: 30-50 characters per line
- •Use
max-width: 65chor similar for text containers
5.3 Typography Characters
- •Use proper ellipsis:
…not... - •Use curly quotes:
""''not straight quotes"' - •Use non-breaking spaces where needed:
10 MB,⌘ K, brand names - •Loading states end with ellipsis:
"Loading…","Saving…"
5.4 Number Formatting
- •Use
font-variant-numeric: tabular-numsfor number columns, comparisons, counters - •Use
text-wrap: balanceortext-wrap: prettyon headings (prevents widows/orphans)
5.5 Font Loading
- •Limit to 2-3 font families
- •Limit to 3 font weights per family
- •Use
font-display: swapfor custom fonts - •Provide fallback font stack
- •Preload critical fonts:
<link rel="preload" as="font" crossorigin>
6. Content Handling
6.1 Text Overflow
- •Text containers must handle long content:
- •
truncate/text-overflow: ellipsis - •
line-clamp-*/-webkit-line-clamp - •
break-words/word-break: break-word
- •
- •Flex children need
min-w-0/min-width: 0to allow text truncation - •Test with very long strings (50+ chars without spaces)
6.2 Empty States
- •Handle empty strings, null, undefined gracefully
- •Handle empty arrays — show meaningful empty state, not broken UI
- •Anticipate: short, average, and very long user inputs
6.3 Content Guidelines
- •Active voice: "Install the CLI" not "The CLI will be installed"
- •Title Case for headings and buttons (Chicago style)
- •Use numerals: "8 deployments" not "eight deployments"
- •Specific button labels: "Save API Key" not "Continue" or "Submit"
- •Error messages include fix/next step, not just the problem
- •Use second person ("you"); avoid first person ("I", "we")
- •Use
&over "and" where space-constrained
7. Images & Media
7.1 Dimensions & Layout Shift
- •
<img>MUST have explicitwidthandheightattributes (prevents CLS) - •Or use
aspect-ratioCSS property - •Reserve space with container aspect ratio
7.2 Loading Strategy
- •Below-fold images:
loading="lazy" - •Above-fold critical images:
fetchpriority="high"or framework'spriority - •Use
decoding="async"for non-critical images
7.3 Optimization
- •Use modern formats: WebP, AVIF
- •Provide responsive images with
srcsetandsizes - •Compress images appropriately
- •Use CDN for image delivery
8. Performance (Core Web Vitals)
8.1 LCP (Largest Contentful Paint)
- •Target: < 2.5 seconds
- •Preload critical resources:
<link rel="preload"> - •Add
<link rel="preconnect">for CDN/asset domains - •Optimize largest image/text block
8.2 CLS (Cumulative Layout Shift)
- •Target: < 0.1
- •Always specify image/video dimensions
- •Reserve space for dynamic content (ads, embeds)
- •Use
scroll-margin-topon heading anchors - •Avoid inserting content above existing content
8.3 INP (Interaction to Next Paint)
- •Target: < 200ms
- •No layout reads during render: avoid
getBoundingClientRect,offsetHeight,offsetWidth,scrollTopin render path - •Batch DOM reads/writes — don't interleave
- •Prefer uncontrolled inputs; controlled inputs must be cheap per keystroke
- •Debounce expensive handlers
8.4 Lists & Virtualization
- •Large lists (>50 items): virtualize with
virtua,react-window,@tanstack/virtual, orcontent-visibility: auto - •Paginate or infinite scroll for large datasets
9. Navigation & State
9.1 URL Reflects State
- •Filters, tabs, pagination, sort order → URL query params
- •Deep-link all stateful UI (if uses
useState, consider URL sync) - •Use libraries like
nuqs,next-usequerystate, or router state
9.2 Links vs Buttons
- •Links (
<a>/<Link>) for navigation — supports Cmd/Ctrl+click, middle-click, right-click → "Open in new tab" - •Buttons (
<button>) for actions that don't navigate
9.3 Destructive Actions
- •Destructive actions need confirmation modal OR undo window
- •NEVER immediate deletion without recovery option
- •Show clear warning about consequences
10. Touch & Mobile Interaction
10.1 Touch Targets
- •Minimum touch target: 44×44px (Apple HIG) or 48×48dp (Material)
- •WCAG 2.2: minimum 24×24 CSS pixels
- •Adequate spacing between targets (8px+ gap)
10.2 Touch Behavior
- •Use
touch-action: manipulation(prevents double-tap zoom delay) - •Set
-webkit-tap-highlight-colorintentionally (or transparent) - •Use
overscroll-behavior: containin modals/drawers/sheets
10.3 Drag & Drop
- •During drag: disable text selection (
user-select: none) - •Use
inerton dragged elements - •Provide keyboard alternative for drag operations (WCAG)
10.4 Focus on Mobile
- •Use
autoFocussparingly — desktop only, single primary input - •Avoid
autoFocuson mobile (may cause viewport jump)
11. Layout & Safe Areas
11.1 Safe Areas
- •Full-bleed layouts need
env(safe-area-inset-*)for notches, home indicators - •Bottom fixed elements:
padding-bottom: env(safe-area-inset-bottom)
11.2 Overflow Management
- •Avoid unwanted scrollbars: check for content overflow
- •Use
overflow-x: hiddencarefully (only when justified) - •Prefer Flexbox/Grid over JavaScript measurement for layout
11.3 Responsive Design
- •Mobile-first approach: start with mobile styles, add larger breakpoints
- •Use fluid typography:
clamp()for font sizes - •Use container queries for component-level responsiveness
- •Test at common breakpoints: 320px, 375px, 768px, 1024px, 1440px
12. Dark Mode & Theming
12.1 System Integration
- •Use
color-scheme: darkon<html>for dark themes (fixes scrollbar, inputs, form controls) - •Match
<meta name="theme-color">to page background - •Native
<select>: set explicitbackground-colorandcolor(Windows dark mode fix)
12.2 User Preference
- •Honor
prefers-color-schememedia query - •Provide manual toggle that persists preference
- •Ensure all UI elements work in both modes
13. Internationalization (i18n)
13.1 Locale-Aware Formatting
- •Dates/times: use
Intl.DateTimeFormat, not hardcoded formats - •Numbers/currency: use
Intl.NumberFormat, not hardcoded formats - •Relative time: use
Intl.RelativeTimeFormat
13.2 Language Detection
- •Detect language via
Accept-Languageheader ornavigator.languages - •NEVER use IP geolocation for language detection
13.3 RTL Support
- •Use logical CSS properties:
margin-inline-startnotmargin-left - •Set
dir="rtl"on<html>for RTL languages - •Test layout in RTL mode
14. Hydration Safety (SSR/SSG)
14.1 Controlled Inputs
- •Inputs with
valueprop MUST haveonChangehandler - •Or use
defaultValuefor uncontrolled inputs
14.2 Client-Only Content
- •Date/time rendering: guard against hydration mismatch (server vs client timezone)
- •Use
suppressHydrationWarningonly where truly needed - •Dynamic content based on
window/localStorage: render client-side only
15. Interactive States
15.1 Hover & Active States
- •Buttons and links MUST have
hover:state (visual feedback) - •Interactive states should increase contrast/prominence
- •Hover → Active → Focus progression should be visually clear
15.2 Disabled States
- •Use
disabledattribute, not just styling - •Disabled elements: reduced opacity (0.5-0.6),
cursor: not-allowed - •Consider
aria-disabled="true"if element should remain focusable
Anti-Patterns Checklist
Flag these immediately:
| Pattern | Issue |
|---|---|
user-scalable=no or maximum-scale=1 | Disables zoom — accessibility violation |
onPaste + preventDefault() | Blocks paste — UX hostile |
transition: all | Performance issue — list properties |
outline: none / outline-none without focus replacement | Removes focus indicator — accessibility violation |
<div onClick> or <span onClick> | Should be <button> or <a> |
<img> without width/height | Causes layout shift (CLS) |
<img> without alt | Missing alt text — accessibility violation |
Form inputs without <label> | Missing label — accessibility violation |
Icon buttons without aria-label | Screen reader can't identify action |
| Hardcoded date/number formats | Should use Intl.* APIs |
autoFocus without clear justification | May cause issues on mobile |
Large arrays with .map() without virtualization | Performance issue for 50+ items |
tabindex > 0 | Disrupts natural tab order |
| Color-only indicators | Fails colorblind users |
| Placeholder as label | Label disappears on input |
Output Format
Group by file. Use file:line format (VS Code/IDE clickable). Terse findings.
## src/components/Button.tsx src/components/Button.tsx:42 - icon button missing aria-label src/components/Button.tsx:18 - input lacks associated label src/components/Button.tsx:55 - animation missing prefers-reduced-motion check src/components/Button.tsx:67 - transition: all → list specific properties src/components/Button.tsx:89 - div with onClick → use <button> ## src/components/Modal.tsx src/components/Modal.tsx:12 - missing overscroll-behavior: contain src/components/Modal.tsx:34 - "..." → use "…" (proper ellipsis) src/components/Modal.tsx:78 - no focus trap for modal dialog ## src/components/Card.tsx ✓ No issues found ## Summary - 8 accessibility issues - 3 performance issues - 2 UX issues - Priority: Fix accessibility issues first (WCAG compliance)
State issue + location. Skip explanation unless fix non-obvious. No preamble.
References
- •WCAG 2.2 Guidelines
- •WAI-ARIA Authoring Practices
- •MDN Accessibility Guide
- •Core Web Vitals
- •prefers-reduced-motion
Related EasyPlatform Docs
- •SCSS Styling Guide - Angular/BEM patterns, platform-specific SCSS conventions
- •Frontend Patterns - Angular component hierarchy, state management
IMPORTANT Task Planning Notes
- •Always plan and break many small todo tasks
- •Always add a final review todo task to review the works done at the end to find any fix or enhancement needed