Building Interfaces That Don't Get in the Way
Good web design isn't about following trends or adding flourishes. It's about removing friction between your users and their goals.

The Problem With Most Web Design
I've built dozens of web applications over the past decade, and I've watched countless projects derail because teams conflated "good design" with "visually impressive." The reality is simpler and harder: good web design means your interface disappears.
When users remember your interface instead of accomplishing their task, you've failed. When they tell their colleagues about a button animation or gradient, you've optimized for the wrong metric. The best interfaces feel obvious in retrospect, almost inevitable.
Start With Information Architecture
Before you open Figma or write a single line of CSS, map out what users need to do and in what order. I use a simple text file:
User lands on homepage
→ Needs to understand what we do (3 seconds or less)
→ Needs to find either pricing or documentation
→ If pricing: compare plans, see what's included
→ If docs: search or browse by category
This isn't a user flow diagram with fifty boxes and arrows. It's a constraint. Every design decision should make these paths more obvious, not less.
I've seen teams spend weeks perfecting a hero section animation while their documentation remains unsearchable and their pricing page requires scrolling through six screens. Prioritize the paths users actually take.
Visual Hierarchy Is Not Optional
Here's a test: take a screenshot of your interface, convert it to grayscale, and blur it slightly. Can you still tell what's important? If everything has the same visual weight, nothing has priority.
I use a three-tier system:
Primary actions: High contrast, prominent placement, usually one per screen. "Sign Up", "Deploy", "Purchase". These get the full-color treatment and adequate spacing.
Secondary actions: Lower contrast, often just text or outline buttons. "Learn More", "Cancel", "View Details". These are available but don't compete with primary actions.
Tertiary content: Metadata, timestamps, supplementary information. Smaller text, muted colors. Present but not distracting.
When you promote everything, you communicate nothing. Be ruthless about hierarchy.
Typography Matters More Than You Think
Your interface is mostly text. Most designers I know obsess over button styles and icons while using 14px body text with insufficient line height. This is backwards.
Start here:
body {
font-size: 16px; /* minimum, never smaller */
line-height: 1.6; /* 1.5 minimum for body text */
max-width: 70ch; /* optimal line length */
font-family: system-ui, -apple-system, sans-serif;
}
h2 {
font-size: 1.75rem;
line-height: 1.3;
margin-top: 2em; /* breathing room */
margin-bottom: 0.5em;
}
System fonts load instantly and feel native. Don't import three weights of a custom typeface for 200ms slower page loads unless you have a compelling reason. Most marketing sites don't.
Set a modular scale for your type sizes. I use 1.25 (major third) as a multiplier: 1rem, 1.25rem, 1.563rem, 1.953rem. Pick a scale, stick to it, and never use arbitrary sizes.
Color Is Communication
I see a lot of interfaces with eight or ten colors in regular use. This is too many. You need:
- A primary color for actions and links
- A darker shade for hover states
- Neutral grays (3-4 shades maximum)
- Success, warning, and error colors
- That's it
Define these once in CSS custom properties:
:root {
--color-primary: #2563eb;
--color-primary-dark: #1e40af;
--color-gray-100: #f3f4f6;
--color-gray-600: #4b5563;
--color-gray-900: #111827;
--color-success: #059669;
--color-warning: #d97706;
--color-error: #dc2626;
}
Every color should mean something. If you're adding a new color, you're probably solving the wrong problem.
Responsive Design Is Not About Breakpoints
Stop thinking in device categories. Design with constraints that flex naturally:
.container {
width: min(90%, 1200px);
padding: clamp(1rem, 5vw, 3rem);
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr));
gap: 2rem;
}
This grid works at any viewport width without media queries. It breaks to fewer columns when space is tight, maintains minimum card widths, and never overflows.
Media queries are for major layout changes, not incremental adjustments. Use CSS functions that respond to available space.
Performance Is Part of Design
Your beautiful interface doesn't matter if it takes four seconds to render. I inline critical CSS (above-the-fold styles), defer non-critical JavaScript, and lazy-load images below the fold:
<img
src="placeholder.jpg"
data-src="full-image.jpg"
loading="lazy"
alt="Descriptive text">
Every dependency you add is a tax on every user forever. That animation library, that icon set, that analytics script—each one costs load time. I've removed more code than I've added in the past year, and every interface got faster and simpler.
Test With Real Content
Lorem ipsum conceals problems. Design with actual copy, real user names, genuine data. What happens when:
- A username is 3 characters? 40 characters?
- A headline wraps to four lines?
- An image fails to load?
- A list has 1 item? 100 items?
Every interface I've built has broken in production because we didn't test edge cases during design. Build loading states, empty states, and error states from the beginning.
Ship and Iterate
The best design decision I ever made was shipping a minimal interface and watching how people actually used it. We were wrong about which features mattered. We were wrong about information hierarchy. We were wrong about where users got stuck.
Design in production. Deploy to a small group, watch session recordings, read support tickets, then adjust. The interface you imagine users need is probably not the interface they actually need.
Good web design is invisible, fast, and gets out of the way. Everything else is decoration.