Common UI Patterns
Users spend most of their time on other apps and websites. They arrive at yours with expectations already set — Jakob's Law. Following established UI conventions means users spend their mental energy on your content, not your interface. Breaking those conventions means friction, confusion, and drop-off.
This page covers the patterns that work, the anti-patterns that don't, and the reasoning behind each.
Navigation
Persistent Navigation
Main navigation should be visible on every page — top bar, sidebar, or both. Users need to always know where they are and how to get somewhere else. Navigation is how users build a mental map of your application; hide it and they get lost.
- Keep primary navigation visible at all times on desktop. Don't hide it behind creative layouts or animations.
- Provide a clear "home" affordance — usually the logo in the top-left corner.
- Use consistent placement across all pages. Moving navigation between pages breaks spatial memory.
- Consider sticky or fixed navigation on long pages so users can navigate without scrolling back to the top.
Anti-pattern: Hiding all navigation behind an unlabeled icon on desktop. The hamburger menu (☰) is understood on mobile — on desktop, it buries discoverability.
Breadcrumbs
Use breadcrumbs for sites with three or more levels of hierarchy. They show users where they are in the structure and provide a fast way to jump up.
- Place breadcrumbs below the main navigation, above the page title.
- Use Schema.org BreadcrumbList markup for SEO benefit.
- Don't rely on breadcrumbs as the only back-navigation — they supplement, not replace, the main nav.
Mobile Navigation
- Bottom tab bar for up to 5 primary destinations. Tabs sit in the thumb-friendly zone and leverage the Serial Position Effect — put the most important items first and last.
- Hamburger menu (☰) for secondary items. It's a universal convention on mobile — users know what it means.
- Never put the only navigation behind a hamburger menu on desktop. Desktop has the screen real estate to show navigation directly.
Active States
Always indicate the current page or section in the navigation. Users should never have to guess where they are.
- Highlight the active nav item with a visual indicator — bold text, underline, background color, or left border.
- Use
aria-current="page"on the active link for screen readers. - See Accessibility as Design for more on accessible navigation.
Anti-patterns to avoid:
- More than 7–8 top-level navigation items — Hick's Law says decision time increases with options.
- Hover-only dropdown menus that disappear when the cursor drifts off by a pixel.
- Identical-looking items that link to different content types (mixing pages, downloads, and external links with no visual distinction).
Form Design
Layout
Single-column forms outperform multi-column layouts. Users complete them roughly 15 seconds faster because there's no ambiguity about reading order (Baymard Institute research). Use a single column unless you have a strong reason not to.
- Group related fields with
<fieldset>and<legend>. - Keep forms as short as possible — every field you can remove increases completion rate (Parkinson's Law).
- Break long forms into logical steps with a progress indicator.
Labels and Placeholders
Place labels above their fields. This layout produces the fastest completion times, works on all screen sizes, and accommodates labels of varying length.
Never use placeholder text as the only label for a form field. Placeholder text disappears when the user starts typing, removing the context they need to verify their input. This is also an accessibility failure — placeholder text typically has insufficient contrast and is not reliably announced by screen readers.
Placeholder text is supplementary. Use it to show format examples ("e.g., jane@example.com") alongside a visible label, never instead of one.
Validation
Validate inline on blur — when the user leaves a field. Don't validate on every keystroke (it's distracting while typing), and don't wait until form submission (it's too late).
- Error messages should say what went wrong and how to fix it: "Password must be at least 8 characters" — not "Invalid password."
- Show all errors at once, not one at a time. Revealing errors sequentially makes users feel like they're playing whack-a-mole.
- Use
aria-describedbyto associate error messages with their fields for screen readers. - Pair the red error color with an icon (⚠️) — color alone is not enough for colorblind users.
Show success states too, not just errors. A green checkmark next to a validated email field gives users confidence that they're on track.
Smart Defaults
Every field you can pre-fill is one less decision for the user.
- Pre-select the most common choice (country, language, currency).
- Use proper
autocompleteattributes so browsers can auto-fill name, email, address, and payment fields. - Auto-detect locale for country, currency, and date format when possible.
- Default radio buttons and toggles to the most common option rather than leaving them unselected.
Submit Buttons
The button label should describe what happens. Use "Create Account" not "Submit." Use "Save Changes" not "OK."
- Place the primary submit button at the bottom-left of the form — the natural terminus of the user's eye flow in LTR layouts.
- Disable the button briefly after click to prevent double-submission, or implement idempotent submission on the server side.
- Show a loading spinner on the button during submission so users know their action was received.
- For destructive actions, use a confirmation step — not just a different button color.
Responsive Design
Mobile-First
Start with the smallest screen, then add complexity as the viewport grows. Use min-width media queries, not max-width:
/* Mobile-first: base styles are mobile */
.card { padding: 1rem; }
/* Add complexity for larger screens */
@media (min-width: 768px) {
.card { padding: 2rem; display: grid; grid-template-columns: 1fr 1fr; }
}
This approach forces prioritization. If the content doesn't fit on a small screen, ask whether it's truly essential.
Breakpoints
Don't design for specific devices — design for where your layout breaks. Test by resizing your browser and adding breakpoints where the content stops looking right.
Common starting points (Tailwind CSS defaults):
| Token | Width | Typical Usage |
|---|---|---|
sm | 640px | Large phones in landscape |
md | 768px | Tablets |
lg | 1024px | Small laptops |
xl | 1280px | Desktops |
2xl | 1536px | Large screens |
These are starting points, not gospel. Adjust based on your content and layout needs.
Fluid Typography
Instead of jumping between fixed sizes at breakpoints, use clamp() for smooth scaling:
h1 {
font-size: clamp(1.875rem, 1rem + 2vw, 2.5rem);
}
body {
font-size: clamp(1rem, 0.5rem + 1.5vw, 1.25rem);
}
No media queries needed. See Visual Design Fundamentals for the full typography section.
Touch Targets
Minimum touch target size: 44×44 CSS pixels (WCAG 2.5.5 AAA). Google Material Design recommends 48×48px.
- Ensure at least 8px of spacing between adjacent interactive targets.
- This is especially critical when destructive actions sit next to safe ones — "Delete" next to "Edit" with no gap is an accident waiting to happen.
- See Accessibility as Design for comprehensive touch target guidance.
Loading States
Timing Thresholds
Match your loading UI to how long the user is waiting. The Doherty Threshold tells us that perceived responsiveness drops sharply after 400ms.
| Response Time | User Perception | Recommended UI |
|---|---|---|
< 100ms | Feels instant | No indicator needed |
| 100–300ms | Slight delay | Subtle indicator (button spinner, disabled state) |
| 300ms–1s | Noticeable wait | Skeleton screen or loading shimmer |
| 1–10s | Significant wait | Progress bar or descriptive message |
> 10s | Too long | Explain what's happening, allow cancel |
Skeleton Screens
Prefer skeleton screens over spinners for content loading. Skeletons show the shape of the upcoming content with pulsing gray placeholders. This approach reduces perceived wait time (users see progress, not emptiness) and prevents Cumulative Layout Shift (CLS) because the skeleton reserves the space the real content will occupy.
.skeleton {
background: linear-gradient(
90deg,
#e5e7eb 25%,
#f3f4f6 50%,
#e5e7eb 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 4px;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
Optimistic Updates
Update the UI immediately on user action, then reconcile with the server in the background. This makes the interface feel instant.
- Best for low-risk, reversible actions: liking, bookmarking, toggling settings, reordering items.
- Roll back the UI change on failure with a clear error message.
- Provide a subtle undo option for reversible actions.
Only use optimistic updates for reversible, low-risk actions. For destructive or financial operations, wait for server confirmation before updating the UI.
Anti-pattern: Full-page loading spinners that block all interaction. Prefer inline, contextual loading states that let users continue interacting with the rest of the page.
Error States
Inline Field Errors
Display errors directly below the field they apply to. Combine multiple signals so the error is unmistakable:
- Red border on the field.
- Error icon (⚠️) — don't rely on color alone, as some users can't distinguish red.
- Descriptive text explaining the problem and how to fix it.
- Use
aria-describedbyto associate the error message with the field for screen readers. - Show all errors at once. Revealing them one at a time forces unnecessary resubmissions.
Error Pages
Error pages are often an afterthought, but they're a critical part of the user experience — especially when something goes wrong.
- 404 (Not Found): Be helpful, not just apologetic. Include search, suggested pages, or navigation links. A dead-end 404 is a lost user.
- 500 (Server Error): Be honest. "We couldn't load your data. Try refreshing the page." — not "An error occurred." Provide a retry action and a way back (link to home, search bar).
- Use plain language in all error pages. Technical jargon helps nobody.
- Include a consistent header and navigation on error pages so users can self-recover.
Network Errors
- Detect offline status with
navigator.onLineandonline/offlineevents. - Show a banner, not a full-page error — users may still have cached content they can read.
- Queue actions for retry when connectivity returns, if your architecture supports it.
Non-Destructive Error Handling
The cardinal rule of error handling: never lose the user's work.
- Never clear form data on submission error — preserve every field the user filled in.
- Never navigate away from the user's current context on error.
- Use toasts for transient, non-critical errors. Auto-dismiss after 5–8 seconds.
- Persist important errors (data loss, payment failure) until the user explicitly dismisses them.
- Don't stack more than 3 toasts at once — it overwhelms the screen and the user.
Empty States
An empty state is a design opportunity, not a blank page.
First-Use Empty States
An empty dashboard on first login is a missed onboarding moment. The user has just committed to your product — this is your chance to guide them.
Instead of a blank screen, show:
- A clear explanation of what will appear here ("No projects yet").
- A primary call-to-action ("Create your first project").
- Optionally, a brief illustration or icon to soften the emptiness.
- If applicable, a sample or template the user can explore before creating their own.
Guide the user toward their first meaningful action. Don't make them figure out how to get started.
No-Results States
When a search or filter returns nothing:
- Show the search term back to confirm what was searched: "No results for 'flutterby'."
- Suggest next steps: check spelling, broaden criteria, try different keywords.
- If possible, show related or popular results as a fallback.
User-Cleared States
When the user has deleted or archived everything in a list:
- Confirm the action succeeded ("All items archived").
- Offer a clear way to add new items or undo the last action.
Anti-pattern: A blank white page with no guidance. A data table showing column headers and zero rows with no explanation. Both leave users wondering if something is broken.
Further Reading
- Laws of UX — The psychological principles behind these patterns.
- Visual Design Fundamentals — Typography, color, spacing, and hierarchy.
- Accessibility as Design — Accessible navigation, forms, and touch targets.
- Design Tools & Resources — Checklist Design, Mobbin, and other pattern references.
- NNGroup — Evidence-based UX research on navigation, forms, error handling, and more.
- Baymard Institute — Form and e-commerce UX research.