129 actionable UX/interface rules (ux-guidelines + web-interface merged), 93 of them with live good ✓ / bad ✗ demos — hover / click to feel the difference. Filter by category; the eight states and anti-patterns live on the Tune tab and in playbook 4.2 §3/§7.
Smooth Scroll
NavigationWeb▶ live demoHighAnchor links should scroll smoothly to target section
Section 1 — Getting started with the basics.
Section 2 — Configuration and options.
Section 3 — Troubleshooting and FAQ.
Section 1 — Getting started with the basics.
Section 2 — Configuration and options.
Section 3 — Troubleshooting and FAQ.
Do Use scroll-behavior: smooth on html element
Don't Jump directly without transition
Code examples
✓ html { scroll-behavior: smooth; }✗ <a href='#section'> without CSS
Active State
NavigationAll▶ live demoMediumCurrent page/section should be visually indicated
Which page are you on?
click a tabWhich page are you on?
click a tabDo Highlight active nav item with color/underline
Don't No visual feedback on current location
Code examples
✓ text-primary border-b-2
✗ All links same style
Back Button
NavigationMobileHighUsers expect back to work predictably
Do Preserve navigation history properly
Don't Break browser/app back button behavior
Code examples
✓ history.pushState()
✗ location.replace()
Deep Linking
NavigationAllMediumURLs should reflect current state for sharing
Do Update URL on state/view changes
Don't Static URLs for dynamic content
Code examples
✓ Use query params or hash
✗ Single URL for all states
Breadcrumbs
NavigationWeb▶ live demoLowShow user location in site hierarchy
Do Use for sites with 3+ levels of depth
Don't Use for flat single-level sites
Code examples
✓ Home > Category > Product
✗ Only on deep nested pages
Excessive Motion
AnimationAll▶ live demoHighToo many animations cause distraction and motion sickness
New in v2.0
New in v2.0
Do Animate 1-2 key elements per view maximum
Don't Animate everything that moves
Code examples
✓ Single hero animation
✗ animate-bounce on 5+ elements
Duration Timing
AnimationAll▶ live demoMediumAnimations should feel responsive not sluggish
200ms — responds as you move
hover me1200ms — still catching up
hover meDo Use 150-300ms for micro-interactions
Don't Use animations longer than 500ms for UI
Code examples
✓ transition-all duration-200
✗ duration-1000
Reduced Motion
AnimationAllHighRespect user's motion preferences
Do Check prefers-reduced-motion media query
Don't Ignore accessibility motion settings
Code examples
✓ @media (prefers-reduced-motion: reduce)
✗ No motion query check
Loading States
AnimationAll▶ live demoHighShow feedback during async operations
Q3 report ready
Revenue up 12% quarter over quarter.
Q3 report ready
Revenue up 12% quarter over quarter.
Do Use skeleton screens or spinners
Don't Leave UI frozen with no feedback
Code examples
✓ animate-pulse skeleton
✗ Blank screen while loading
Hover vs Tap
AnimationAll▶ live demoHighHover effects don't work on touch devices
Do Use click/tap for primary interactions
Don't Rely only on hover for important actions
Code examples
✓ onClick handler
✗ onMouseEnter only
Continuous Animation
AnimationAll▶ live demoMediumInfinite animations are distracting
Motion = something is happening
Motion = nothing, forever
Do Use for loading indicators only
Don't Use for decorative elements
Code examples
✓ animate-spin on loader
✗ animate-bounce on icons
Transform Performance
AnimationWebMediumSome CSS properties trigger expensive repaints
Do Use transform and opacity for animations
Don't Animate width/height/top/left properties
Code examples
✓ transform: translateY()
✗ top: 10px animation
Easing Functions
AnimationAll▶ live demoLowLinear motion feels robotic
ease-out — arrives, then settles
hover melinear — conveyor-belt motion
hover meDo Use ease-out for entering ease-in for exiting
Don't Use linear for UI transitions
Code examples
✓ ease-out
✗ linear
Z-Index Management
LayoutWebHighStacking context conflicts cause hidden elements
Do Define z-index scale system (10 20 30 50)
Don't Use arbitrary large z-index values
Code examples
✓ z-10 z-20 z-50
✗ z-[9999]
Fixed Positioning
LayoutWeb▶ live demoMediumFixed elements can overlap or be inaccessible
Inbox — 3 new messages
Drafts — 1 saved
Archive — all clear
Inbox — 3 new messages
Drafts — 1 saved
Archive — all clear
Do Account for safe areas and other fixed elements
Don't Stack multiple fixed elements carelessly
Code examples
✓ Fixed nav + fixed bottom with gap
✗ Multiple overlapping fixed elements
Stacking Context
LayoutWeb▶ live demoMediumNew stacking contexts reset z-index
Do Understand what creates new stacking context
Don't Expect z-index to work across contexts
Code examples
✓ Parent with z-index isolates children
✗ z-index: 9999 not working
Content Jumping
LayoutWeb▶ live demoHighLayout shift when content loads is jarring
Sunset over the harbor
Shot on a rainy Tuesday.
Sunset over the harbor
Shot on a rainy Tuesday.
Do Reserve space for async content
Don't Let images/content push layout around
Code examples
✓ aspect-ratio or fixed height
✗ No dimensions on images
Viewport Units
LayoutWebMedium100vh can be problematic on mobile browsers
Do Use dvh or account for mobile browser chrome
Don't Use 100vh for full-screen mobile layouts
Code examples
✓ min-h-dvh or min-h-screen
✗ h-screen on mobile
Container Width
LayoutWeb▶ live demoMediumContent too wide is hard to read
Readable lines end after a comfortable measure, so your eye finds the next line without losing its place on the way back.
Readable lines end after a comfortable measure, so your eye finds the next line without losing its place on the way back. When text runs edge to edge across the whole container the return sweep gets longer and longer, rereads creep in, and the paragraph turns into a wall.
Do Limit max-width for text content (65-75ch)
Don't Let text span full viewport width
Code examples
✓ max-w-prose or max-w-3xl
✗ Full width paragraphs
Touch Target Size
TouchMobile▶ live demoHighSmall buttons are hard to tap accurately
44×44px
try tapping24×24px, 2px apart
try tappingDo Minimum 44x44px touch targets
Don't Tiny clickable areas
Code examples
✓ min-h-[44px] min-w-[44px]
✗ w-6 h-6 buttons
Touch Spacing
TouchMobile▶ live demoMediumAdjacent touch targets need adequate spacing
Do Minimum 8px gap between touch targets
Don't Tightly packed clickable elements
Code examples
✓ gap-2 between buttons
✗ gap-0 or gap-1
Gesture Conflicts
TouchMobile▶ live demoMediumCustom gestures can conflict with system
Do Avoid horizontal swipe on main content
Don't Override system gestures
Code examples
✓ Vertical scroll primary
✗ Horizontal swipe carousel only
Tap Delay
TouchMobileMedium300ms tap delay feels laggy
Do Use touch-action CSS or fastclick
Don't Default mobile tap handling
Code examples
✓ touch-action: manipulation
✗ No touch optimization
Pull to Refresh
TouchMobile▶ live demoLowAccidental refresh is frustrating
Do Disable where not needed
Don't Enable by default everywhere
Code examples
✓ overscroll-behavior: contain
✗ Default overscroll
Haptic Feedback
TouchMobileLowTactile feedback improves interaction feel
Do Use for confirmations and important actions
Don't Overuse vibration feedback
Code examples
✓ navigator.vibrate(10)
✗ Vibrate on every tap
Focus States
InteractionAll▶ live demoHighKeyboard users need visible focus indicators
Do Use visible focus rings on interactive elements
Don't Remove focus outline without replacement
Code examples
✓ focus:ring-2 focus:ring-blue-500
✗ outline-none without alternative
Hover States
InteractionWeb▶ live demoMediumVisual feedback on interactive elements
Do Change cursor and add subtle visual change
Don't No hover feedback on clickable elements
Code examples
✓ hover:bg-gray-100 cursor-pointer
✗ No hover style
Active States
InteractionAll▶ live demoMediumShow immediate feedback on press/click
Do Add pressed/active state visual change
Don't No feedback during interaction
Code examples
✓ active:scale-95
✗ No active state
Disabled States
InteractionAll▶ live demoMediumClearly indicate non-interactive elements
Do Reduce opacity and change cursor
Don't Confuse disabled with normal state
Code examples
✓ opacity-50 cursor-not-allowed
✗ Same style as enabled
Loading Buttons
InteractionAll▶ live demoHighPrevent double submission during async actions
Do Disable button and show loading state
Don't Allow multiple clicks during processing
Code examples
✓ disabled={loading} spinner✗ Button clickable while loading
Error Feedback
InteractionAll▶ live demoHighUsers need to know when something fails
Do Show clear error messages near problem
Don't Silent failures with no feedback
Code examples
✓ Red border + error message
✗ No indication of error
Success Feedback
InteractionAll▶ live demoMediumConfirm successful actions to users
Do Show success message or visual change
Don't No confirmation of completed action
Code examples
✓ Toast notification or checkmark
✗ Action completes silently
Confirmation Dialogs
InteractionAll▶ live demoHighPrevent accidental destructive actions
Do Confirm before delete/irreversible actions
Don't Delete without confirmation
Code examples
✓ Are you sure modal
✗ Direct delete on click
Color Contrast
AccessibilityAll▶ live demoHighText must be readable against background
Order #4821 arrives Tuesday.
Order #4821 arrives Tuesday.
Do Minimum 4.5:1 ratio for normal text
Don't Low contrast text
Code examples
✓ #333 on white (7:1)
✗ #999 on white (2.8:1)
Color Only
AccessibilityAll▶ live demoHighDon't convey information by color alone
Do Use icons/text in addition to color
Don't Red/green only for error/success
Code examples
✓ Red text + error icon
✗ Red border only for error
Alt Text
AccessibilityAll▶ live demoHighImages need text alternatives
Do Descriptive alt text for meaningful images
Don't Empty or missing alt attributes
Code examples
✓ alt='Dog playing in park'
✗ alt='' for content images
Heading Hierarchy
AccessibilityWebMediumScreen readers use headings for navigation
Do Use sequential heading levels h1-h6
Don't Skip heading levels or misuse for styling
Code examples
✓ h1 then h2 then h3
✗ h1 then h4
ARIA Labels
AccessibilityAllHighInteractive elements need accessible names
Do Add aria-label for icon-only buttons
Don't Icon buttons without labels
Code examples
✓ aria-label='Close menu'
✗ <button><Icon/></button>
Screen Reader
AccessibilityAllMediumContent should make sense when read aloud
Do Use semantic HTML and ARIA properly
Don't Div soup with no semantics
Code examples
✓ <nav> <main> <article>
✗ <div> for everything
Form Labels
AccessibilityAll▶ live demoHighInputs must have associated labels
Do Use label with for attribute or wrap input
Don't Placeholder-only inputs
Code examples
✓ <label for='email'>
✗ placeholder='Email' only
Error Messages
AccessibilityAllHighError messages must be announced
Do Use aria-live or role=alert for errors
Don't Visual-only error indication
Code examples
✓ role='alert'
✗ Red border only
Skip Links
AccessibilityWeb▶ live demoMediumAllow keyboard users to skip navigation
Do Provide skip to main content link
Don't No skip link on nav-heavy pages
Code examples
✓ Skip to main content link
✗ 100 tabs to reach content
Image Optimization
PerformanceAllHighLarge images slow page load
Do Use appropriate size and format (WebP)
Don't Unoptimized full-size images
Code examples
✓ srcset with multiple sizes
✗ 4000px image for 400px display
Lazy Loading
PerformanceAllMediumLoad content as needed
Do Lazy load below-fold images and content
Don't Load everything upfront
Code examples
✓ loading='lazy'
✗ All images eager load
Code Splitting
PerformanceWebMediumLarge bundles slow initial load
Do Split code by route/feature
Don't Single large bundle
Code examples
✓ dynamic import()
✗ All code in main bundle
Caching
PerformanceWebMediumRepeat visits should be fast
Do Set appropriate cache headers
Don't No caching strategy
Code examples
✓ Cache-Control headers
✗ Every request hits server
Font Loading
PerformanceWeb▶ live demoMediumWeb fonts can block rendering
Welcome back, Sarah. You have three tasks due today, one review waiting on your approval, and a design critique at four this afternoon.
webfont "arrives" on a loop — nothing movesWelcome back, Sarah. You have three tasks due today, one review waiting on your approval, and a design critique at four this afternoon.
watch the button jump on font loadDo Use font-display swap or optional
Don't Invisible text during font load
Code examples
✓ font-display: swap
✗ FOIT (Flash of Invisible Text)
Third Party Scripts
PerformanceWebMediumExternal scripts can block rendering
Do Load non-critical scripts async/defer
Don't Synchronous third-party scripts
Code examples
✓ async or defer attribute
✗ <script src='...'> in head
Bundle Size
PerformanceWebMediumLarge JavaScript slows interaction
Do Monitor and minimize bundle size
Don't Ignore bundle size growth
Code examples
✓ Bundle analyzer
✗ No size monitoring
Render Blocking
PerformanceWebMediumCSS/JS can block first paint
Do Inline critical CSS defer non-critical
Don't Large blocking CSS files
Code examples
✓ Critical CSS inline
✗ All CSS in head
Input Labels
FormsAll▶ live demoHighEvery input needs a visible label
Do Always show label above or beside input
Don't Placeholder as only label
Code examples
✓ <label>Email</label><input>
✗ placeholder='Email' only
Error Placement
FormsAll▶ live demoMediumErrors should appear near the problem
Do Show error below related input
Don't Single error message at top of form
Code examples
✓ Error under each field
✗ All errors at form top
Inline Validation
FormsAll▶ live demoMediumValidate as user types or on blur
Do Validate on blur for most fields
Don't Validate only on submit
Code examples
✓ onBlur validation
✗ Submit-only validation
Input Types
FormsAll▶ live demoMediumUse appropriate input types
Do Use email tel number url etc
Don't Text input for everything
Code examples
✓ type='email'
✗ type='text' for email
Autofill Support
FormsWebMediumHelp browsers autofill correctly
Do Use autocomplete attribute properly
Don't Block or ignore autofill
Code examples
✓ autocomplete='email'
✗ autocomplete='off' everywhere
Required Indicators
FormsAll▶ live demoMediumMark required fields clearly
Do Use asterisk or (required) text
Don't No indication of required fields
Code examples
✓ * required indicator
✗ Guess which are required
Password Visibility
FormsAll▶ live demoMediumLet users see password while typing
Do Toggle to show/hide password
Don't No visibility toggle
Code examples
✓ Show/hide password button
✗ Password always hidden
Submit Feedback
FormsAll▶ live demoHighConfirm form submission status
Do Show loading then success/error state
Don't No feedback after submit
Code examples
✓ Loading -> Success message
✗ Button click with no response
Input Affordance
FormsAll▶ live demoMediumInputs should look interactive
Do Use distinct input styling
Don't Inputs that look like plain text
Code examples
✓ Border/background on inputs
✗ Borderless inputs
Mobile Keyboards
FormsMobileMediumShow appropriate keyboard for input type
Do Use inputmode attribute
Don't Default keyboard for all inputs
Code examples
✓ inputmode='numeric'
✗ Text keyboard for numbers
Mobile First
ResponsiveWebMediumDesign for mobile then enhance for larger
Do Start with mobile styles then add breakpoints
Don't Desktop-first causing mobile issues
Code examples
✓ Default mobile + md: lg: xl:
✗ Desktop default + max-width queries
Breakpoint Testing
ResponsiveWebMediumTest at all common screen sizes
Do Test at 320 375 414 768 1024 1440
Don't Only test on your device
Code examples
✓ Multiple device testing
✗ Single device development
Touch Friendly
ResponsiveWeb▶ live demoHighMobile layouts need touch-sized targets
Do Increase touch targets on mobile
Don't Same tiny buttons on mobile
Code examples
✓ Larger buttons on mobile
✗ Desktop-sized targets on mobile
Readable Font Size
ResponsiveAll▶ live demoHighText must be readable on all devices
Your order ships tomorrow. Track it anytime from your account page.
Your order ships tomorrow. Track it anytime from your account page.
Do Minimum 16px body text on mobile
Don't Tiny text on mobile
Code examples
✓ text-base or larger
✗ text-xs for body text
Viewport Meta
ResponsiveWebHighSet viewport for mobile devices
Do Use width=device-width initial-scale=1
Don't Missing or incorrect viewport
Code examples
✓ <meta name='viewport'...>
✗ No viewport meta tag
Horizontal Scroll
ResponsiveWeb▶ live demoHighAvoid horizontal scrolling
Content wraps to fit whatever width the screen gives it.
This layout is a fixed 480px wide, whatever your screen says.
Do Ensure content fits viewport width
Don't Content wider than viewport
Code examples
✓ max-w-full overflow-x-hidden
✗ Horizontal scrollbar on mobile
Image Scaling
ResponsiveWeb▶ live demoMediumImages should scale with container
Fluid: fills its container, never spills.
Fixed 420px: the right side is cut off.
Do Use max-width: 100% on images
Don't Fixed width images overflow
Code examples
✓ max-w-full h-auto
✗ width='800' fixed
Table Handling
ResponsiveWeb▶ live demoMediumTables can overflow on mobile
| Invoice | Date | Customer | Amount | Status |
|---|---|---|---|---|
| #1042 | Aug 2 | Acme Corp | $1,250 | Paid |
| #1043 | Aug 3 | Northwind | $840 | Due |
| Invoice | Date | Customer | Amount | Status |
|---|---|---|---|---|
| #1042 | Aug 2 | Acme Corp | $1,250 | Paid |
| #1043 | Aug 3 | Northwind | $840 | Due |
Do Use horizontal scroll or card layout
Don't Wide tables breaking layout
Code examples
✓ overflow-x-auto wrapper
✗ Table overflows viewport
Line Height
TypographyAll▶ live demoMediumAdequate line height improves readability
Line spacing gives each row of text room to breathe, so your eye finds the start of the next line without effort and reading feels easy.
Line spacing gives each row of text room to breathe, so your eye finds the start of the next line without effort and reading feels easy.
Do Use 1.5-1.75 for body text
Don't Cramped or excessive line height
Code examples
✓ leading-relaxed (1.625)
✗ leading-none (1)
Line Length
TypographyWeb▶ live demoMediumLong lines are hard to read
A comfortable measure of roughly 65 to 75 characters lets your eye travel a short, predictable distance before it sweeps back, so you land on the next line without losing your place and reading long passages stays effortless.
A comfortable measure of roughly 65 to 75 characters lets your eye travel a short, predictable distance before it sweeps back, so you land on the next line without losing your place and reading long passages stays effortless.
Do Limit to 65-75 characters per line
Don't Full-width text on large screens
Code examples
✓ max-w-prose
✗ Full viewport width text
Font Size Scale
TypographyAll▶ live demoMediumConsistent type hierarchy aids scanning
Quarterly report
Revenue summary
Sales grew 12% over the previous quarter, led by the new starter plan.
Updated Aug 4 · Finance team
Quarterly report
Revenue summary
Sales grew 12% over the previous quarter, led by the new starter plan.
Updated Aug 4 · Finance team
Do Use consistent modular scale
Don't Random font sizes
Code examples
✓ Type scale (12 14 16 18 24 32)
✗ Arbitrary sizes
Font Loading
TypographyWeb▶ live demoMediumFonts should load without layout shift
Welcome back, Sarah. You have three tasks due today, one review waiting on your approval, and a design critique at four this afternoon.
webfont "arrives" on a loop — nothing movesWelcome back, Sarah. You have three tasks due today, one review waiting on your approval, and a design critique at four this afternoon.
watch the button jump on font loadDo Reserve space with fallback font
Don't Layout shift when fonts load
Code examples
✓ font-display: swap + similar fallback
✗ No fallback font
Contrast Readability
TypographyAll▶ live demoHighBody text needs good contrast
Your subscription renews on August 12. Cancel anytime before then at no charge.
Your subscription renews on August 12. Cancel anytime before then at no charge.
Do Use darker text on light backgrounds
Don't Gray text on gray background
Code examples
✓ text-gray-900 on white
✗ text-gray-400 on gray-100
Heading Clarity
TypographyAll▶ live demoMediumHeadings should stand out from body
Shipping policy
Orders placed before 2pm ship the same day. Free returns within 30 days.
Payment
We accept all major cards and invoicing for teams.
Shipping policy
Orders placed before 2pm ship the same day. Free returns within 30 days.
Payment
We accept all major cards and invoicing for teams.
Do Clear size/weight difference
Don't Headings similar to body text
Code examples
✓ Bold + larger size
✗ Same size as body
Loading Indicators
FeedbackAll▶ live demoHighShow system status during waits
Do Show spinner/skeleton for operations > 300ms
Don't No feedback during loading
Code examples
✓ Skeleton or spinner
✗ Frozen UI
Empty States
FeedbackAll▶ live demoMediumGuide users when no content exists
No projects yet
Projects keep your tasks and files together.
Do Show helpful message and action
Don't Blank empty screens
Code examples
✓ No items yet. Create one!
✗ Empty white space
Error Recovery
FeedbackAll▶ live demoMediumHelp users recover from errors
Upload failed — the connection dropped.
Upload failed.
Do Provide clear next steps
Don't Error without recovery path
Code examples
✓ Try again button + help link
✗ Error message only
Progress Indicators
FeedbackAll▶ live demoMediumShow progress for multi-step processes
Step 1 of 3 — Account
Account
click Next — how much is left?Do Step indicators or progress bar
Don't No indication of progress
Code examples
✓ Step 2 of 4 indicator
✗ No step information
Toast Notifications
FeedbackAll▶ live demoMediumTransient messages for non-critical info
Do Auto-dismiss after 3-5 seconds
Don't Toasts that never disappear
Code examples
✓ Auto-dismiss toast
✗ Persistent toast
Confirmation Messages
FeedbackAll▶ live demoMediumConfirm successful actions
Do Brief success message
Don't Silent success
Code examples
✓ Saved successfully toast
✗ No confirmation
Truncation
ContentAll▶ live demoMediumHandle long content gracefully
Migration notes: moving the billing service to the new region, rotating keys, and updating every webhook consumer before the cutover window
Migration notes: moving the billing service to the new region, rotating keys, and updating every webhook consumer before the cutover window
Do Truncate with ellipsis and expand option
Don't Overflow or broken layout
Code examples
✓ line-clamp-2 with expand
✗ Overflow or cut off
Date Formatting
ContentAll▶ live demoLowUse locale-appropriate date formats
Looks good — merging after the tests pass.
Looks good — merging after the tests pass.
Jan 2? Feb 1? 2003?Do Use relative or locale-aware dates
Don't Ambiguous date formats
Code examples
✓ 2 hours ago or locale format
✗ 01/02/03
Number Formatting
ContentAll▶ live demoLowFormat large numbers for readability
Do Use thousand separators or abbreviations
Don't Long unformatted numbers
Code examples
✓ 1.2K or 1,234
✗ 1234567
Placeholder Content
ContentAll▶ live demoLowShow realistic placeholders during dev
Designing checkout flows at Klarna. Previously led design systems at a fintech startup.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.
does the layout survive real names?Do Use realistic sample data
Don't Lorem ipsum everywhere
Code examples
✓ Real sample content
✗ Lorem ipsum
User Freedom
OnboardingAll▶ live demoMediumUsers should be able to skip tutorials
Your dashboard
Tip 1 of 3: pin your favorite reports here.
Your dashboard
Tip 1 of 3: pin your favorite reports here.
Do Provide Skip and Back buttons
Don't Force linear unskippable tour
Code examples
✓ Skip Tutorial button
✗ Locked overlay until finished
Autocomplete
SearchWeb▶ live demoMediumHelp users find results faster
Do Show predictions as user types
Don't Require full type and enter
Code examples
✓ Debounced fetch + dropdown
✗ No suggestions
No Results
SearchWeb▶ live demoMediumDead ends frustrate users
Do Show 'No results' with suggestions
Don't Blank screen or '0 results'
Code examples
✓ Try searching for X instead
✗ No results found.
Bulk Actions
Data EntryWeb▶ live demoLowEditing one by one is tedious
Do Allow multi-select and bulk edit
Don't Single row actions only
Code examples
✓ Checkbox column + Action bar
✗ Repeated actions per row
Disclaimer
AI InteractionAll▶ live demoHighUsers need to know they talk to AI
Do Clearly label AI generated content
Don't Present AI as human
Code examples
✓ AI Assistant label
✗ Fake human name without label
Streaming
AI InteractionAll▶ live demoMediumWaiting for full text is slow
Do Stream text response token by token
Don't Show loading spinner for 10s+
Code examples
✓ Typewriter effect
✗ Spinner until 100% complete
Gaze Hover
Spatial UIVisionOSHighElements should respond to eye tracking before pinch
Do Scale/highlight element on look
Don't Static element until pinch
Code examples
✓ hoverEffect()
✗ onTap only
Depth Layering
Spatial UIVisionOS▶ live demoMediumUI needs Z-depth to separate content from environment
Do Use glass material and z-offset
Don't Flat opaque panels blocking view
Code examples
✓ .glassBackgroundEffect()
✗ bg-white
Auto-Play Video
SustainabilityWeb▶ live demoMediumVideo consumes massive data and energy
Do Click-to-play or pause when off-screen
Don't Auto-play high-res video loops
Code examples
✓ playsInline muted preload='none'
✗ autoplay loop
Asset Weight
SustainabilityWebMediumHeavy 3D/Image assets increase carbon footprint
Do Compress and lazy load 3D models
Don't Load 50MB textures
Code examples
✓ Draco compression
✗ Raw .obj files
Feedback Loop
AI InteractionAll▶ live demoLowAI needs user feedback to improve
Paris is the capital of France.
Paris is the capital of France.
wrong or unhelpful? tough luckDo Thumps up/down or 'Regenerate'
Don't Static output only
Code examples
✓ Feedback component
✗ Read-only text
Motion Sensitivity
AccessibilityAll▶ live demoHighParallax/Scroll-jacking causes nausea
Do Respect prefers-reduced-motion
Don't Force scroll effects
Code examples
✓ @media (prefers-reduced-motion)
✗ ScrollTrigger.create()
Icon Button Labels
AccessibilityWeb▶ live demoCriticalIcon-only buttons must have accessible names
Do Add aria-label to icon buttons
Don't Icon button without label
Code examples
✓ <button aria-label='Close'><XIcon /></button>
✗ <button><XIcon /></button>
Form Control Labels
AccessibilityWeb▶ live demoCriticalAll form controls need labels or aria-label
Do Use label element or aria-label
Don't Input without accessible name
Code examples
✓ <label for='email'>Email</label><input id='email' />
✗ <input placeholder='Email' />
Keyboard Handlers
AccessibilityWeb▶ live demoHighInteractive elements must support keyboard interaction
Cart: 0
Tab to it, press EnterCart: 0
Tab… you can never reach itDo Add onKeyDown alongside onClick
Don't Click-only interaction
Code examples
✓ <div onClick={fn} onKeyDown={fn} tabIndex={0}>✗ <div onClick={fn}>Semantic HTML
AccessibilityWeb▶ live demoHighUse semantic HTML before ARIA attributes
<button> — Tab + Enter/Space free of charge
<div role="button"> — looks same, keyboard dead
Do Use button/a/label elements
Don't Div with role attribute
Code examples
✓ <button onClick={fn}>Submit</button>✗ <div role='button' onClick={fn}>Submit</div>Aria Live
AccessibilityWeb▶ live demoMediumAsync updates need aria-live for screen readers
Screen reader hears: —
click saveScreen reader hears: —
click save — silenceDo Add aria-live='polite' for dynamic content
Don't Silent async updates
Code examples
✓ <div aria-live='polite'>{status}</div>✗ <div>{status}</div> // no announcementDecorative Icons
AccessibilityWeb▶ live demoMediumDecorative icons should be hidden from screen readers
Do Add aria-hidden='true' to decorative icons
Don't Decorative icon announced
Code examples
✓ <Icon aria-hidden='true' />
✗ <Icon /> // announced as 'image'
Visible Focus States
FocusWeb▶ live demoCriticalAll interactive elements need visible focus states
Do Use :focus-visible with ring/outline
Don't No focus indication
Code examples
✓ focus-visible:ring-2 focus-visible:ring-blue-500
✗ outline-none // no replacement
Never Remove Outline
FocusWeb▶ live demoCriticalNever remove outline without providing replacement
Do Replace outline with visible alternative
Don't Remove outline completely
Code examples
✓ focus:outline-none focus:ring-2
✗ focus:outline-none // nothing else
Checkbox Radio Hit Target
FocusWeb▶ live demoMediumCheckbox/radio must share hit target with label
Do Wrap input and label together
Don't Separate tiny checkbox
Code examples
✓ <label class='flex gap-2'><input type='checkbox' /><span>Option</span></label>
✗ <input type='checkbox' id='x' /><label for='x'>Option</label>
Autocomplete Attribute
FormsWebHighInputs need autocomplete attribute for autofill
Do Add appropriate autocomplete value
Don't Missing autocomplete
Code examples
✓ <input autocomplete='email' type='email' />
✗ <input type='email' />
Semantic Input Types
FormsWeb▶ live demoMediumUse semantic input type attributes
Do Use email/tel/url/number types
Don't text type for everything
Code examples
✓ <input type='email' />
✗ <input type='text' /> // for email
Never Block Paste
FormsWeb▶ live demoHighNever prevent paste functionality
X7-K2-9Q
copy the code, paste it here
X7-K2-9Q
Paste blocked — type it by hand
try pasting — it's blocked
Do Allow paste on all inputs
Don't Block paste on password/code
Code examples
✓ <input type='password' />
✗ <input onPaste={e => e.preventDefault()} />Spellcheck Disable
FormsWebLowDisable spellcheck on emails and codes
Do Set spellcheck='false' on codes
Don't Spellcheck on technical input
Code examples
✓ <input spellCheck='false' type='email' />
✗ <input type='email' /> // red squiggles
Submit Button Enabled
FormsWeb▶ live demoMediumKeep submit enabled and show spinner during requests
Do Show loading spinner keep enabled
Don't Disable button during submit
Code examples
✓ <button>{loading ? <Spinner /> : 'Submit'}</button>✗ <button disabled={loading}>Submit</button>Inline Errors
FormsWeb▶ live demoHighShow error messages inline near the problem field
Do Inline error with focus on first error
Don't Single error at top
Code examples
✓ <input /><span class='text-red-500'>{error}</span>✗ <div class='error'>{allErrors}</div> // at topVirtualize Lists
PerformanceWebHighVirtualize lists exceeding 50 items
Do Use virtual list for large datasets
Don't Render all items
Code examples
✓ <VirtualList items={items} />✗ items.map(item => <Item />)
Avoid Layout Reads
PerformanceWebMediumAvoid layout reads during render phase
Do Read layout in effects or callbacks
Don't getBoundingClientRect in render
Code examples
✓ useEffect(() => { el.getBoundingClientRect() })✗ const rect = el.getBoundingClientRect() // in render
Batch DOM Operations
PerformanceWebMediumGroup DOM operations to minimize reflows
Do Batch writes then reads
Don't Interleave reads and writes
Code examples
✓ writes.forEach(w => w()); reads.forEach(r => r())
✗ write(); read(); write(); read(); // thrashing
Preconnect CDN
PerformanceWebAdd preconnect links for CDN domains
Do Preconnect to known domains
Don't <link rel='preconnect' href='https://cdn.example.com' />
Code examples
✓ // no preconnect hint
✗ Low
Lazy Load Images
PerformanceWebMediumLazy-load images below the fold
Do Use loading='lazy' for below-fold images
Don't Load all images eagerly
Code examples
✓ <img loading='lazy' src='...' />
✗ <img src='...' /> // above fold only
URL Reflects State
StateWeb▶ live demoHighURL should reflect current UI state
Do Sync filters/tabs/pagination to URL
Don't State only in memory
Code examples
✓ ?tab=settings&page=2
✗ useState only // lost on refresh
Deep Linking
StateWebMediumStateful components should support deep-linking
Do Enable sharing current view via URL
Don't No shareable state
Code examples
✓ router.push({ query: { ...filters } })✗ setFilters(f) // not in URL
Confirm Destructive Actions
StateWeb▶ live demoHighDestructive actions require confirmation
Do Show confirmation dialog before delete
Don't Delete without confirmation
Code examples
✓ if (confirm('Delete?')) delete()✗ onClick={delete} // no confirmationProper Unicode
TypographyWeb▶ live demoLowUse proper Unicode characters
Loading… ellipsis
“Nice work” curly quotes
2019–2024 en dash
It’s ready apostrophe
Loading... three dots
"Nice work" straight quotes
2019-2024 hyphen
It's ready typewriter tick
Do Use ... curly quotes proper dashes
Don't ASCII approximations
Code examples
✓ 'Hello...' with proper ellipsis
✗ 'Hello...' with three dots
Text Overflow
TypographyWeb▶ live demoMediumHandle text overflow properly
Do Use truncate/line-clamp/break-words
Don't Text overflows container
Code examples
✓ <p class='truncate'>Long text...</p>
✗ <p>Long text...</p> // overflows
Non-Breaking Spaces
TypographyWeb▶ live demoUse non-breaking spaces for units and brand names
Maximum weight 10 kg
Maximum weight 10 kg
Do Use between number and unit
Don't 10 kg or Next.js 14
Code examples
✓ 10 kg // may wrap
✗ Low
No Zoom Disable
Anti-PatternWebNever disable zoom in viewport meta
Do Allow user zoom
Don't <meta name='viewport' content='width=device-width'>
Code examples
✓ <meta name='viewport' content='maximum-scale=1'>
✗ Critical
No Transition All
Anti-PatternWeb▶ live demoMediumAvoid transition: all - specify properties
Do Transition specific properties
Don't transition: all
Code examples
✓ transition-colors duration-200
✗ transition-all duration-200
Outline Replacement
Anti-PatternWeb▶ live demoCriticalNever use outline-none without replacement
Do Provide visible focus replacement
Don't Remove outline with nothing
Code examples
✓ focus:outline-none focus:ring-2 focus:ring-blue-500
✗ focus:outline-none // alone
No Hardcoded Dates
Anti-PatternWeb▶ live demoMediumUse Intl for date/number formatting
Do Use Intl.DateTimeFormat
Don't Hardcoded date format
Code examples
✓ new Intl.DateTimeFormat('en').format(date)✗ date.toLocaleDateString() // or manual format