Color and typography are the two fastest ways to make a project look professional — or amateur. Getting these right transforms "developer project" into "real product."
Color Theory Essentials
The Color Wheel
You don't need to memorize color theory. Just understand three relationships:
| Scheme | Description | Use Case |
|---|---|---|
| Complementary | Opposite on the wheel (blue + orange) | High contrast, CTAs |
| Analogous | Adjacent on the wheel (blue + teal + green) | Harmonious, calm |
| Triadic | Evenly spaced (blue + red + yellow) | Vibrant, balanced |
Building a Palette
Every UI needs these colors:
Primary → Your brand color (buttons, links, accents)
Secondary → Supporting color (tags, badges, highlights)
Neutral → Grays for text, backgrounds, borders
Success → Green for positive states
Warning → Yellow/orange for caution
Error → Red for errors and destructive actionsThe 60-30-10 Rule
- 60% — Dominant color (background, large surfaces) — usually neutral
- 30% — Secondary color (cards, sections, secondary elements)
- 10% — Accent color (buttons, links, highlights) — your primary brand color
This creates balance. If you use your brand color on 60% of the page, it's overwhelming.
Choosing Colors in Practice
Start with one color you like. Then build around it:
- Pick your primary brand color
- Choose 1-2 neutral grays (one for text, one for backgrounds)
- Add semantic colors (success green, error red, warning yellow)
- Generate shades (lighter and darker versions) for each
Contrast and Accessibility
Text must have enough contrast against its background to be readable.
| Level | Ratio | Requirement |
|---|---|---|
| AA Normal text | 4.5:1 | Minimum for body text |
| AA Large text | 3:1 | Text 18px+ or 14px bold |
| AAA Normal text | 7:1 | Enhanced readability |
/* Good contrast */
color: #1a1a1a; /* Dark text */
background: #ffffff; /* White background */
/* Ratio: 16.8:1 ✓ */
/* Bad contrast */
color: #999999; /* Gray text */
background: #ffffff; /* White background */
/* Ratio: 2.8:1 ✗ */Use tools like WebAIM Contrast Checker to verify your color combinations.
Dark Mode
For dark mode, don't just invert colors. Instead:
- Use dark grays (#1a1a1a, #2a2a2a) instead of pure black (#000000)
- Reduce brightness of your accent colors slightly
- Use lighter text (#e0e0e0) instead of pure white (#ffffff) for body text
- Increase spacing slightly — dark backgrounds make things feel tighter
Typography
Choosing Fonts
You need at most two fonts:
| Role | Type | Examples |
|---|---|---|
| Headings | Sans-serif or display | Inter, Manrope, Outfit |
| Body text | Sans-serif or serif | Inter, Source Serif, Georgia |
| Code | Monospace | JetBrains Mono, Fira Code |
Pairing rules:
- One serif + one sans-serif usually works (Source Serif + Inter)
- Two fonts from the same family work (Inter + Inter)
- Avoid two fonts that are too similar but not the same
- When in doubt, use one font family for everything
Type Scale
A type scale creates consistent, harmonious sizes. Don't pick random numbers — use a ratio.
1.250 ratio (major third) — good for most UIs:
12px — Caption, labels
14px — Small text, metadata
16px — Body text (base)
20px — Large text, H4
25px — H3
31px — H2
39px — H1
49px — Display/heroIn CSS:
:root {
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.25rem; /* 20px */
--text-xl: 1.563rem; /* 25px */
--text-2xl: 1.953rem; /* 31px */
--text-3xl: 2.441rem; /* 39px */
--text-4xl: 3.052rem; /* 49px */
}Line Height
Line height (leading) affects readability dramatically:
| Text Type | Line Height |
|---|---|
| Body text | 1.5 - 1.7 |
| Headings | 1.1 - 1.3 |
| Captions | 1.4 |
| Buttons | 1.0 |
body { line-height: 1.6; }
h1, h2, h3 { line-height: 1.2; }Line Length
The ideal line length for body text is 45-75 characters per line (about 65 is optimal).
/* Set a max-width on text containers */
.prose {
max-width: 65ch; /* ~65 characters wide */
}Lines that are too long are hard to track across the page. Lines that are too short break the reading rhythm.
Font Weight
Use weight to create hierarchy:
h1 { font-weight: 700; } /* Bold for main headings */
h2 { font-weight: 600; } /* Semi-bold for subheadings */
p { font-weight: 400; } /* Regular for body text */
/* Never use more than 3 weights from the same font */Letter Spacing
Adjust letter spacing for specific cases:
/* Uppercase text needs more spacing */
.uppercase-label {
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 0.75rem;
}
/* Large headings can be tighter */
h1 {
letter-spacing: -0.02em;
}Putting It Together
A complete CSS setup:
:root {
/* Colors */
--color-primary: #2563eb;
--color-text: #1a1a1a;
--color-text-secondary: #6b7280;
--color-bg: #ffffff;
--color-bg-secondary: #f9fafb;
--color-border: #e5e7eb;
--color-success: #16a34a;
--color-error: #dc2626;
/* Typography */
--font-sans: 'Inter', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
/* Spacing */
--space-1: 4px;
--space-2: 8px;
--space-3: 16px;
--space-4: 24px;
--space-5: 32px;
--space-6: 48px;
}
body {
font-family: var(--font-sans);
font-size: 16px;
line-height: 1.6;
color: var(--color-text);
background: var(--color-bg);
}Summary
- Build a palette with primary, secondary, neutral, and semantic colors
- Follow the 60-30-10 rule for color distribution
- Ensure text contrast meets WCAG AA (4.5:1 for normal text)
- Use at most 2 font families and 3 font weights
- Establish a type scale using a consistent ratio
- Body text: 16px base, 1.5-1.7 line height, 45-75 characters per line
- Dark mode: dark grays, not pure black; reduced accent brightness