A Crash Course on Design for Devs
You do not need to be a designer to make things look good. If you are a developer, a few simple design principles will take your UI from functional to professional. This crash course distills the essentials so you can apply them quickly and move on.
Introduction
You've built the feature. It works. But something feels... off. The spacing looks random, the colors clash, and you can't pinpoint why. This guide fixes that.
Design is not about making things pretty. It is about making decisions obvious, content readable, and interactions smooth. By learning a few simple rules, you can take your UI from "hacky" to "professional" without needing years of design training.
Think of design like coding: small consistent rules add up to a system that feels polished and intentional.
Start with Hierarchy
Good design is about guiding attention. Ask: what is the most important thing on this screen? Make it bigger, bolder, or more prominent. Secondary info should fade into the background. When everything is emphasized equally, nothing stands out.
Stop Guessing: Try the 8-Point Grid
One of the hardest parts of design is picking values. Why 15px padding and not 16px? To save mental energy, try using the 8-Point Grid System.
The idea is simple: use multiples of 8 (or 4) for all spacing and sizing.
- Small spacing: 4px, 8px
- Medium spacing: 16px, 24px, 32px
- Large spacing: 48px, 64px
If 16px feels too tight, don't try 17px. Jump straight to 24px. This limitation actually frees you up. It creates a vertical rhythm that makes the UI feel subconsciously "correct" to the user.
Create a Theme and Stick With It
Decide on a set of colors, font choices, border radius, and spacing rules and then use them everywhere. A cohesive theme makes your app feel deliberate. Constantly switching styles feels messy, like mixing coding styles in one file.
Pick One or Two Fonts
You do not need ten fonts. One typeface with bold, regular, and italic weights plus a monospace for code is usually enough. Consistency here avoids visual clutter. Use font weight and size for emphasis instead of grabbing a new font.
Define a Type Scale
Just like spacing, font sizes should follow a scale. Don't guess between 15px and 16px. Pick a set and stick to it.
- Small: 12px, 14px
- Body: 16px
- Headings: 20px, 24px, 32px
Jumping from 16px to 18px is barely noticeable. Jumping from 16px to 20px creates clear hierarchy.
Balance Your Colors with 60-30-10
A common mistake is using a brand color (like heavy blue) everywhere. To fix this, you can borrow a rule from interior design called 60-30-10.
Think of a man in a business suit: 60% is the slacks and jacket (neutral), 30% is the shirt (secondary), and 10% is the tie (accent).
- 60% Neutral: This is your canvas. Whites, creams, or soft grays. It should cover the majority of the screen (backgrounds, negative space).
- 30% Secondary: This supports the content. Medium grays for text, light borders, or subtle card backgrounds.
- 10% Accent: This is your "Action Color." Use it strictly for the things you want users to click, like primary buttons or active states.
If your UI feels overwhelming, check your ratio. You likely have too much "10%" (buttons, badges, links) and not enough "60%".
Contrast Makes Text Readable
Light gray on slightly lighter gray? Do not. Text should stand out clearly from its background. High contrast improves both readability and accessibility. If you are ever unsure, make the text darker, not lighter.
Alignment Creates Order
Left align text, align buttons and inputs to a grid, and keep spacing consistent. When elements do not line up, the design feels chaotic even if the colors and fonts are perfect. Alignment gives instant polish.
Group Related Things Together
Use proximity to show relationships. Headings should sit close to the text they belong to. Buttons that apply to a form should live inside or just under that form, not floating somewhere else. This reduces cognitive load.
Reuse Styles Instead of Inventing New Ones
If you have a card component, reuse the same border radius, padding, and shadow style across the app. Consistency makes things look deliberate. Inconsistency makes things look hacked together.
Icons Should Clarify
Icons should support meaning. A trash can for delete, a plus for add, a gear for settings. Decorative icons that do not add clarity just distract.
Start Simple, Polish Later
Do not overthink your first pass. Get something clear and usable on the screen. Add refinement like colors, shadows, and micro interactions after the layout and hierarchy work. Design is iterative just like code.
Quick Wins (Common Mistakes)
- Avoid Pure Black: Pure black (
#000000) naturally spreads and can cause eye strain on bright screens. Use a dark gray like#111or#1A1A1A. - Don't Center Long Text: Centered text is hard to read for paragraphs. Left-align body text.
- Clickable vs. Disabled: Low contrast gray buttons look disabled. Make sure your secondary buttons still look interactive (e.g., use a border or decent contrast).
The Developer’s Advantage
As a developer, you already think in systems. That is what design really is: consistent rules, components, and constraints. Treat your UI like a codebase, refactor messy parts, reuse components, and apply patterns consistently.
Putting It All Together: A Component Refactor
Let's look at a common scenario: a simple user card.
Before
Please view user profile below:
jane@example.com
After
Profile Details
Jane Doe
jane@example.com
The "Before" State Here is a typical "developer-first" implementation. It works, but it feels "off". The spacing is random, the hierarchy is confused (why is the "Admin" badge so loud?), and the colors clash.
// ❌ BEFORE: "Almost" right, but subtly off
// - Arbitrary values (p-[15px]) break the rhythm
// - Blue background on Admin badge distracts from the primary action
// - Badge and Button compete for attention
const UserCardBefore = () => (
<div className="border border-[#e5e5e5] rounded-[6px] p-[15px]">
<div className="flex justify-between mb-[12px]">
<span className="text-[18px] font-semibold">Jane Doe</span>
<span className="bg-[#3b82f6] text-white px-[8px] py-[4px] rounded-[4px] text-[12px]">
Admin
</span>
</div>
<p className="text-[#666] mb-[15px]">jane@example.com</p>
<button className="bg-[#3b82f6] text-white py-[10px] px-[16px] w-full rounded-[6px] font-semibold">
Edit Profile
</button>
</div>
);
The "After" State Now, let's apply the principles:
- 8pt Grid: Changed padding to
16px(p-4). - Hierarchy: Made the "Admin" tag smaller and softer to de-emphasize it.
- Color: Swapped the harsh black border for a soft gray shadow.
// ✅ AFTER: Systematized and Polish
// - Spacing is consistent (multiples of 4)
// - Colors use a "Scale" (gray-500, gray-900) rather than random picks
// - Primary action is clear but doesn't scream at you
const UserCardGood = () => (
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 max-w-sm">
<div className="flex justify-between items-start mb-4">
<div>
<h3 className="text-lg font-semibold text-gray-900">Jane Doe</h3>
<p className="text-sm text-gray-500">jane@example.com</p>
</div>
<span className="bg-gray-100 text-gray-600 text-xs px-2 py-1 rounded-full">
Admin
</span>
</div>
<button className="w-full mt-2 px-4 py-2 bg-white border border-gray-300 text-gray-700 font-medium rounded-md hover:bg-gray-50 transition-colors">
Edit Profile
</button>
</div>
);