Frontend Engineer

Building Better User Interfaces

Most UI advice is vague. "Keep it simple." "Use whitespace." "Be consistent." That's fine, but it doesn't help when you're staring at a screen trying to decide how to lay out a settings page.

Here are specific things I've learned that actually make interfaces better.

Get the typography right first

Typography is 90% of most UIs. If your text looks good, the whole page looks good. If it doesn't, no amount of fancy components will save it.

A solid starting point:

  • Body text: 16px (1rem), line-height 1.6-1.7
  • Headings: Same font, just bump up the weight (500-600) instead of making them huge
  • Secondary text: 14px, lower opacity (0.5-0.6) instead of a separate gray color
  • Max line width: 65-75 characters. Long lines are hard to read

The Inter font works for almost everything. Geist by Vercel is another solid choice. Don't spend hours picking fonts, just pick one of these and move on.

Use opacity instead of gray

Instead of defining 5 shades of gray (#333, #666, #999, #ccc, #eee), use one text color with different opacity levels:

.primary-text   { color: #1a1a1a; }
.secondary-text { color: #1a1a1a; opacity: 0.6; }
.muted-text     { color: #1a1a1a; opacity: 0.4; }

This works because opacity naturally creates a consistent visual hierarchy. Everything feels cohesive because it's the same color at different intensities. It also makes switching to dark mode simpler, swap the base color and all the variants update automatically.

Spacing matters more than colors

The difference between amateur and professional UI is usually spacing, not colors or fancy effects. A few rules that always work:

Use consistent spacing scales. Don't use random values like 13px, 17px, 22px. Stick to a scale: 4, 8, 12, 16, 24, 32, 48, 64. Tailwind's spacing scale (p-1 through p-16) is built on this.

Group related things together, separate unrelated things. The space between a heading and its content should be smaller than the space between two sections. This is the Law of Proximity and it's one of the most powerful design principles.

Give elements room to breathe. When in doubt, add more padding. A button with px-6 py-3 almost always looks better than px-3 py-1.

Make loading states feel fast

Users don't mind waiting if it feels like something is happening. Here are three patterns:

Skeleton screens instead of spinners. Show the shape of the content before the data loads. It makes the page feel faster because the layout doesn't jump when data arrives. Shadcn's Skeleton component is a good reference.

Optimistic updates for user actions. When someone clicks "Like," update the UI immediately and sync with the server in the background. If the request fails, revert. The user never waits for a round-trip.

Instant page transitions with prefetching. In Next.js, the <Link> component prefetches pages automatically on hover. Pages feel instant because the data is already loaded by the time the user clicks.

Use real content during design

Don't design with "Lorem ipsum" or perfectly formatted placeholder data. Use real content because that's what will actually break your layout.

  • What happens when a name is 40 characters long?
  • What about an empty state with zero items?
  • How does a paragraph look with one sentence vs five?

The earlier you test with real content, the fewer surprises you'll have. Tools like Faker.js can generate realistic test data.

Subtle animations, not flashy ones

Animation should guide attention, not distract. The best animations are ones users don't consciously notice:

  • Hover transitions: 150ms ease on color/background changes
  • Page transitions: 200-300ms for elements entering the screen
  • Micro-interactions: Buttons that scale slightly on press (active:scale-95)

Keep durations under 300ms for interactive elements. Anything longer and the UI starts feeling sluggish. Framer Motion is the go-to library for React animations when you need more than CSS transitions.

Steal from the best

The fastest way to build good UI is to look at apps you like and study what they do. Some that consistently nail it:

  • Linear for keyboard-first interaction design
  • Vercel for clean, minimal layouts
  • Stripe for typography and content hierarchy
  • Raycast for speed and polish

Inspect their spacing, font sizes, colors, and transitions. You'll notice they all follow the same basic principles: consistent spacing, restrained color use, and subtle motion.

Tools that help

  • Tailwind CSS gives you a system for spacing, colors, and typography out of the box. Instead of inventing values, you use the scale.
  • Shadcn/ui provides well-designed, accessible components you can copy into your project and customize.
  • Radix Primitives handles the hard accessibility and interaction patterns (dropdowns, modals, tooltips) so you can focus on the visual design.
  • Figma for prototyping layouts before writing code. Even rough mockups save time.

The one thing that matters most

Ship it. Show it to someone. Watch them use it.

No amount of reading about UI will replace watching a real person get confused by something you thought was obvious. Build, ship, observe, iterate. That's how good interfaces get made.