Guide / 25 min

Design Principles for Software Engineers: The Complete Guide

Master visual design fundamentals for building better interfaces. Gestalt psychology, typography, color theory, spacing systems, animation principles, and lessons from design legends like Dieter Rams. Includes case studies of 16 exceptional products.

Design Principles for Software Engineers: The Complete Guide

Updated January 17, 2026

January 2026 Update: This guide consolidates timeless design principles with modern implementation patterns for web and iOS development. It covers Gestalt psychology, typography systems, color theory, visual hierarchy, spacing, and animation—plus lessons from Dieter Rams. See Design Studies for deep dives into 16 exceptional products.

I’ve spent years studying design while building software, absorbing principles from legends like Dieter Rams and dissecting interfaces from products like Linear, Stripe, and Raycast. This guide distills that understanding into the comprehensive reference I wish existed when I started caring about how my software looked and felt.

Design isn’t decoration. It’s communication. Every pixel communicates function, hierarchy, and meaning. The difference between software that feels amateur and software that feels professional is understanding these principles and applying them consistently.

This guide assumes you can already write code. It teaches you to see—to understand why some interfaces feel effortless while others feel chaotic, and more importantly, how to build the former.


Table of Contents

Part 1: Foundations

  1. Gestalt Psychology
  2. Typography
  3. Color Theory
  4. Visual Hierarchy
  5. Spacing & Rhythm
  6. Animation Principles

Part 2: Design Philosophy

  1. Dieter Rams: Ten Principles

Part 3: Implementation

  1. Web Patterns 2025
  2. Design Tokens System
  3. Dark Mode Done Right
  4. Figma Extraction Workflows

Part 4: Reference

  1. Quick Reference Tables
  2. Design Checklist
  3. Design Studies

Gestalt Psychology

“The whole is other than the sum of its parts.” — Kurt Koffka

Gestalt psychology, developed in 1920s Germany, explains how humans perceive visual information. The brain doesn’t see individual pixels—it organizes elements into meaningful patterns. Master these principles to control how users perceive your interfaces.

Proximity

Elements close together are perceived as a group.

This is the most powerful Gestalt principle in UI design. Space communicates relationship more than any other visual property.

WRONG (equal spacing = no grouping):
┌─────────────────┐
│ Label           │
│                 │
│ Input Field     │
│                 │
│ Label           │
│                 │
│ Input Field     │
└─────────────────┘

RIGHT (unequal spacing = clear groups):
┌─────────────────┐
│ Label           │
│ Input Field     │ ← Tight (4px) - related
│                 │
│                 │ ← Wide (24px) - separating groups
│ Label           │
│ Input Field     │ ← Tight (4px) - related
└─────────────────┘

CSS Implementation:

.form-group {
  margin-bottom: 24px;  /* Between groups: wide */
}

.form-group label {
  margin-bottom: 4px;   /* Label to input: tight */
  display: block;
}

SwiftUI Implementation:

VStack(alignment: .leading, spacing: 4) {  // Tight within group
    Text("Email")
        .font(.caption)
        .foregroundStyle(.secondary)
    TextField("[email protected]", text: $email)
        .textFieldStyle(.roundedBorder)
}
.padding(.bottom, 24)  // Wide between groups

Similarity

Elements sharing visual characteristics appear related.

When elements look the same, users assume they function the same. This is why design systems use consistent button styles, card treatments, and typography.

Example Navigation:
┌───────────────────────────────────┐
│ [Dashboard] [Projects] [Settings] │  ← Same style = same function
│                                   │
│ ┌─────┐  ┌─────┐  ┌─────┐        │
│ │Card │  │Card │  │Card │         │  ← Same style = same content type
│ └─────┘  └─────┘  └─────┘        │
│                                   │
│ [+ New Project]                   │  ← Different style = different function
└───────────────────────────────────┘

Figure-Ground

Content should clearly separate from background.

The brain needs to distinguish the “figure” (what to focus on) from the “ground” (the background). Poor figure-ground relationships create visual confusion.

Techniques: - Contrast (light figure on dark ground, or vice versa) - Shadows (elevate figure above ground) - Borders (delineate figure edges) - Blur (blur background, sharpen figure)

/* Strong figure-ground relationship */
.card {
  background: var(--color-surface);     /* Figure */
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);  /* Elevation */
}

.modal-overlay {
  background: rgba(0, 0, 0, 0.5);  /* Dim ground */
  backdrop-filter: blur(4px);      /* Blur ground */
}

Common Region

Elements within a boundary are perceived as grouped.

Enclosing elements within a visual container (card, box, bordered area) signals they belong together.

Continuity

The eye follows paths, lines, and curves.

Use alignment and visual flow to guide attention through your interface.

CONTINUITY IN ALIGNMENT:
┌────────────────────────────────┐
│ Logo    [Nav]  [Nav]  [Nav]   │  ← Aligned on horizontal axis
├────────────────────────────────┤
│                                │
│ Headline                       │
│ ─────────────────────────────  │  ← Eye follows left edge
│ Paragraph text continues       │
│ along the same left edge       │
│                                │
│ [Primary Action]               │  ← Still on the left edge
└────────────────────────────────┘

Closure

The brain completes incomplete shapes.

Users don’t need every pixel drawn—they’ll mentally complete familiar shapes. This allows for more minimal, elegant designs.

/* Horizontal scroll with partial card (closure) */
.card-carousel {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  padding-right: 48px;  /* Show partial card = scroll hint */
}

.card-carousel .card {
  flex: 0 0 280px;  /* Fixed width, partial visible */
}

Gestalt Quick Reference

Principle Rule Primary Use
Proximity Related = close, unrelated = far Form fields, content sections
Similarity Same look = same function Buttons, cards, navigation
Figure-Ground Clear separation of layers Cards, modals, overlays
Common Region Boundaries group content Settings sections, user cards
Continuity Follow lines and alignment Timelines, reading flow
Closure Brain completes shapes Icons, scroll hints, skeletons

Typography

“Typography is the craft of endowing human language with a durable visual form.” — Robert Bringhurst

Typography is the foundation of interface design. Text communicates functionality, hierarchy, and brand. Poor typography makes interfaces harder to use; great typography is invisible—it just works.

Type Scale

A consistent scale creates visual harmony. Use a mathematical ratio.

The 1.25 Scale (Recommended for UI):

:root {
  /* Base: 16px (1rem) */
  --text-xs: 0.64rem;    /* 10.24px - use sparingly */
  --text-sm: 0.8rem;     /* 12.8px - captions, labels */
  --text-base: 1rem;     /* 16px - body text */
  --text-lg: 1.25rem;    /* 20px - lead text */
  --text-xl: 1.563rem;   /* 25px - h4 */
  --text-2xl: 1.953rem;  /* 31.25px - h3 */
  --text-3xl: 2.441rem;  /* 39px - h2 */
  --text-4xl: 3.052rem;  /* 48.8px - h1 */
}

Line Height (Leading)

Line height dramatically affects readability. Different content needs different leading.

Content Type Line Height Why
Headlines 1.1 - 1.2 Tight, bold, short
UI Text 1.3 - 1.4 Labels, buttons
Body Text 1.5 - 1.7 Readable paragraphs
Long-form 1.7 - 2.0 Articles, documentation

Line Length (Measure)

Optimal line length prevents eye fatigue and improves reading comprehension.

  • Optimal: 45-75 characters per line
  • Target: 50-65 characters
  • Absolute max: 85 characters
p {
  max-width: 65ch;  /* ch unit = width of '0' character */
}

.article-body {
  max-width: 70ch;
  margin: 0 auto;
}

Font Selection

System fonts first. They load instantly, match the platform, and are optimized for screens.

:root {
  --font-sans: system-ui, -apple-system, BlinkMacSystemFont,
               'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  --font-mono: ui-monospace, 'SF Mono', 'Cascadia Code',
               'JetBrains Mono', Consolas, monospace;
}

Use custom fonts for: - Brand differentiation (marketing sites) - Editorial/publication feel - Specific design intent not achievable with system fonts

Font Weight for Hierarchy

Use weight to establish hierarchy, not just size.

h1 { font-weight: 700; }  /* Bold */
h2 { font-weight: 600; }  /* Semibold */
h3 { font-weight: 600; }  /* Semibold */
.lead { font-weight: 500; }  /* Medium */
p { font-weight: 400; }   /* Regular */
.meta { font-weight: 400; color: var(--text-muted); }

Typography Quick Reference

Property Body Text Headlines UI Labels
Size 16-18px 24-48px 12-14px
Weight 400 600-700 500
Line Height 1.5-1.7 1.1-1.2 1.3-1.4
Line Length 45-75ch N/A N/A
Alignment Left Center OK Left

Color Theory

“Color is a power which directly influences the soul.” — Wassily Kandinsky

Color communicates faster than words. It establishes mood, guides attention, signals meaning, and builds brand recognition.

The 60-30-10 Rule

The most reliable color distribution for balanced interfaces.

┌──────────────────────────────────────────┐
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ 60% - Dominant (Background)
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 30% - Secondary (Cards, sections)
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓██████▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 10% - Accent (Buttons, links)
└──────────────────────────────────────────┘

Building a Color Palette

Every interface needs these semantic colors:

:root {
  /* Brand */
  --color-primary: hsl(220, 80%, 50%);
  --color-primary-hover: hsl(220, 80%, 45%);

  /* Semantic */
  --color-success: hsl(142, 76%, 36%);  /* Green - positive */
  --color-warning: hsl(38, 92%, 50%);   /* Amber - caution */
  --color-error: hsl(0, 84%, 60%);      /* Red - danger */

  /* Neutrals */
  --color-background: hsl(0, 0%, 100%);
  --color-surface: hsl(220, 14%, 96%);
  --color-border: hsl(220, 13%, 91%);

  /* Text */
  --color-text: hsl(220, 13%, 13%);
  --color-text-secondary: hsl(220, 9%, 46%);
  --color-text-muted: hsl(220, 9%, 64%);
}

Color Psychology

Color Psychology UI Usage
Blue Trust, stability, calm Finance, tech, corporate
Green Growth, nature, success Health, eco, positive states
Red Energy, urgency, danger Alerts, sales, errors
Orange Warmth, enthusiasm CTAs, playful brands
Yellow Optimism, caution Warnings, highlights
Purple Luxury, creativity Premium products

Accessibility Contrast

Level Normal Text Large Text UI Components
AA 4.5:1 3:1 3:1
AAA 7:1 4.5:1 N/A

Tools: WebAIM Contrast Checker, Chrome DevTools color picker


Visual Hierarchy

“Design is the silent ambassador of your brand.” — Paul Rand

Visual hierarchy controls what users see first, second, and third. Without clear hierarchy, users must work to find information. With it, interfaces feel effortless.

The Six Tools of Hierarchy

1. Size — Larger elements attract attention first

.hero-title { font-size: 3rem; }      /* Dominant */
.section-title { font-size: 1.5rem; } /* Secondary */
.body-text { font-size: 1rem; }       /* Baseline */

2. Weight — Bold pops forward, light recedes

h1 { font-weight: 700; }
.lead { font-weight: 500; }
p { font-weight: 400; }

3. Color & Contrast — High contrast = attention

.title { color: var(--color-text); }  /* Near black */
.meta { color: var(--color-text-muted); }  /* Gray */

4. Position — Key positions matter

F-PATTERN (content pages):     Z-PATTERN (landing pages):
████████████████████████      1 ──────────────────► 2
████████                            ↘
████                                     ↘
██                                            ↘
                                   3 ──────────────────► 4

5. Whitespace — Isolation creates importance

.hero { padding: 120px 48px; }  /* Generous space */
.data-table { padding: 12px; }  /* Dense content */

6. Depth & Elevation — Elements that pop forward demand attention

:root {
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
  --shadow-md: 0 4px 6px rgba(0,0,0,0.1);
  --shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
}

.card { box-shadow: var(--shadow-sm); }
.card:hover { box-shadow: var(--shadow-md); }
.modal { box-shadow: var(--shadow-lg); }

The Squint Test

Squint at your design. Can you still see the hierarchy? If yes, it’s strong.


Spacing & Rhythm

“Whitespace is like air: it is necessary for design to breathe.” — Wojciech Zieliński

Spacing is the invisible structure of design. Consistent spacing creates visual rhythm—the feeling that elements belong together in a coherent system.

The 8px Grid

The 8px grid is the industry standard because: - Divides evenly (8, 16, 24, 32, 40, 48…) - Works with common screen densities (1x, 1.5x, 2x, 3x) - Creates consistent rhythm without math

:root {
  --space-1: 4px;    /* Tight: icon gaps */
  --space-2: 8px;    /* Compact: inline elements */
  --space-3: 12px;   /* Snug: form fields */
  --space-4: 16px;   /* Default: most gaps */
  --space-6: 24px;   /* Spacious: card padding */
  --space-8: 32px;   /* Section gaps */
  --space-12: 48px;  /* Major sections */
  --space-16: 64px;  /* Page sections */
  --space-20: 80px;  /* Hero spacing */
}

Internal vs External Spacing

Internal (padding): Space inside an element External (margin): Space between elements

Rule: Internal spacing should typically be larger than external spacing within related groups.

.card {
  padding: 24px;        /* Internal: spacious */
  margin-bottom: 16px;  /* External: less than padding */
}

Component Spacing Patterns

Cards:

.card { padding: 24px; border-radius: 12px; }
.card-header { margin-bottom: 16px; }
.card-title { margin-bottom: 4px; }  /* Tight to subtitle */

Buttons:

.btn { padding: 12px 24px; border-radius: 8px; }
.btn--sm { padding: 8px 16px; }
.btn--lg { padding: 16px 32px; }
.btn-group { display: flex; gap: 12px; }

Forms:

.form-row { margin-bottom: 24px; }
.form-label { margin-bottom: 4px; }
.form-help { margin-top: 4px; }
.form-actions { margin-top: 32px; display: flex; gap: 12px; }

Spacing Quick Reference

Context Recommended Spacing
Icon to text 4-8px
Label to input 4px
Between form groups 24px
Card padding 20-24px
Card gap 16-24px
Section padding (mobile) 48-64px
Section padding (desktop) 80-96px
Button padding (h/v) 24px / 12px

Animation Principles

“Animation is not the art of drawings that move but the art of movements that are drawn.” — Norman McLaren

Animation brings interfaces to life. Done well, it guides attention, communicates state, and creates emotional connection. Done poorly, it frustrates and distracts.

The Core Principle

Animation should feel inevitable, not decorative.

Good animation: 1. Communicates something that static design cannot 2. Reduces cognitive load by showing relationships 3. Feels natural and expected 4. Disappears from conscious awareness

Bad animation: 1. Exists only because “it looks cool” 2. Slows down the user 3. Calls attention to itself 4. Creates anxiety or impatience

Key Principles for UI

1. Anticipation — Prepare users for what’s coming.

.button {
  transition: transform 0.1s ease-out;
}

.button:active {
  transform: scale(0.97);  /* Slight press before action */
}

2. Follow-Through — Let motion complete naturally with spring-like settling.

.panel {
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
withAnimation(.spring(response: 0.4, dampingFraction: 0.7)) {
    isOpen = true
}

3. Ease-In, Ease-Out — Nothing in nature moves at constant speed.

Curve When to Use Character
ease-out Entering elements Quick start, gentle stop
ease-in Exiting elements Gentle start, quick exit
ease-in-out State changes Smooth throughout
linear Loading indicators Continuous, mechanical

4. Staging — Direct attention to what matters. Only one thing should move at a time unless choreographed as a group.

5. Staggering — Elements should arrive in sequence, not all at once.

.list-item {
  animation: fadeSlideIn 0.3s ease-out both;
}

.list-item:nth-child(1) { animation-delay: 0ms; }
.list-item:nth-child(2) { animation-delay: 50ms; }
.list-item:nth-child(3) { animation-delay: 100ms; }
.list-item:nth-child(4) { animation-delay: 150ms; }

@keyframes fadeSlideIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

Timing Guidelines

Duration Use Case Feel
50-100ms Micro-interactions (hover, press) Instant feedback
150-200ms Simple state changes (toggle, select) Snappy
250-350ms Medium transitions (panel slide, card flip) Smooth
400-500ms Large movements (page transitions, modals) Deliberate

Performance: The Golden Rule

Only animate transform and opacity — these are GPU-accelerated and don’t trigger layout.

/* BAD: Animating layout */
.panel { transition: left 0.3s, width 0.3s; }

/* GOOD: Using transform */
.panel { transition: transform 0.3s; }

When NOT to Animate

  1. User has prefers-reduced-motion enabled css @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } }

  2. Animation adds no information — gratuitous spinners, bouncing elements

  3. Users are in a hurry — error states, form validation, search results
  4. Animation would slow repeated actions — keyboard shortcuts should bypass animation

Animation Quick Reference

:root {
  /* Durations */
  --duration-instant: 0.1s;
  --duration-fast: 0.15s;
  --duration-normal: 0.25s;
  --duration-slow: 0.4s;

  /* Easings */
  --ease-out: cubic-bezier(0.0, 0.0, 0.58, 1.0);
  --ease-in: cubic-bezier(0.42, 0.0, 1.0, 1.0);
  --ease-in-out: cubic-bezier(0.42, 0.0, 0.58, 1.0);
  --ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
}

Dieter Rams: Ten Principles

“Less, but better.” — Dieter Rams

Dieter Rams is the most influential industrial designer of the 20th century. As head of design at Braun from 1961-1995, he created products that remain timeless decades later. His work directly inspired Apple’s design language.

The Ten Principles of Good Design

1. Good design is innovative Don’t copy. Pair advancing technology with innovative design.

2. Good design makes a product useful Every element must serve a purpose. Form follows function.

3. Good design is aesthetic Beauty isn’t superficial—it’s essential. Products we use daily affect our well-being.

4. Good design makes a product understandable Users shouldn’t need instructions. The interface teaches itself.

5. Good design is unobtrusive Design should support, not overwhelm. The user’s content is the star, not your UI.

/* Obtrusive: UI competes with content */
.editor {
  background: linear-gradient(135deg, purple, blue);
  border: 3px dashed gold;
}

/* Unobtrusive: UI recedes, content shines */
.editor {
  background: var(--color-background);
  border: 1px solid var(--color-border);
}

6. Good design is honest Don’t use dark patterns. Don’t over-promise. Be transparent about limitations.

7. Good design is long-lasting Avoid trends that will date quickly. Classic over trendy.

TRENDY (will date):           TIMELESS:
- Extreme glassmorphism       - Clean typography
- Neon colors, glitch effects - Subtle elevation
- Aggressive gradients        - Neutral palette with considered accent

8. Good design is thorough down to the last detail Nothing must be arbitrary. Loading states, empty states, error states—all designed.

9. Good design is environmentally friendly Performance is environmental. Respect user attention. Efficient code.

10. Good design is as little design as possible Remove everything that isn’t necessary. The best design is invisible.


Web Patterns 2025

Modern web design leverages native CSS capabilities that eliminate the need for JavaScript in many cases.

Container Queries

Size components based on their container, not the viewport.

.card-grid {
  container-type: inline-size;
  container-name: card-grid;
}

.card {
  display: grid;
  gap: 16px;
  padding: 20px;
}

@container card-grid (min-width: 400px) {
  .card {
    grid-template-columns: auto 1fr;
  }
}

@container card-grid (min-width: 600px) {
  .card {
    padding: 32px;
    gap: 24px;
  }
}

The :has() Selector

Parent selection based on children—previously impossible without JavaScript.

/* Card with image gets different padding */
.card:has(img) {
  padding: 0;
}

.card:has(img) .card-content {
  padding: 20px;
}

/* Form group with error */
.form-group:has(.input:invalid) .form-label {
  color: var(--color-error);
}

/* Highlight navigation when on that page */
.nav-item:has(a[aria-current="page"]) {
  background: var(--color-surface);
}

CSS Nesting

Native nesting without preprocessors.

.card {
  background: var(--color-surface);
  border-radius: 12px;
  padding: 24px;

  & .card-title {
    font-size: 1.25rem;
    font-weight: 600;
    margin-bottom: 8px;
  }

  & .card-body {
    color: var(--color-text-secondary);
    line-height: 1.6;
  }

  &:hover {
    box-shadow: var(--shadow-md);
  }

  @media (min-width: 768px) {
    padding: 32px;
  }
}

HTMX Integration

Server-driven interactivity without heavy JavaScript frameworks.

<!-- Load content on click -->
<button hx-get="/api/more-items"
        hx-target="#item-list"
        hx-swap="beforeend"
        hx-indicator="#loading">
  Load More
</button>

<!-- Form with inline validation -->
<form hx-post="/api/contact"
      hx-target="#form-response"
      hx-swap="outerHTML">
  <input type="email" name="email"
         hx-post="/api/validate-email"
         hx-trigger="blur"
         hx-target="next .error" />
  <span class="error"></span>
</form>

Design Tokens System

A complete token system for consistency across your application.

:root {
  /* Colors */
  --color-text: #1a1a1a;
  --color-text-secondary: #666666;
  --color-text-muted: #999999;

  --color-background: #ffffff;
  --color-surface: #f8f9fa;
  --color-surface-elevated: #ffffff;

  --color-border: #e5e7eb;
  --color-primary: #3b82f6;
  --color-primary-hover: #2563eb;

  --color-success: #10b981;
  --color-warning: #f59e0b;
  --color-error: #ef4444;

  /* Typography */
  --font-sans: system-ui, -apple-system, sans-serif;
  --font-mono: "SF Mono", Consolas, monospace;

  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 2rem;

  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.75;

  /* Spacing (8px base) */
  --space-1: 0.25rem;   /* 4px */
  --space-2: 0.5rem;    /* 8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-6: 1.5rem;    /* 24px */
  --space-8: 2rem;      /* 32px */
  --space-12: 3rem;     /* 48px */
  --space-16: 4rem;     /* 64px */

  /* Borders */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);

  /* Transitions */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 100ms;
  --duration-normal: 200ms;
}

Dark Mode Done Right

Don’t just invert—redesign for dark contexts.

@media (prefers-color-scheme: dark) {
  :root {
    /* Neutrals */
    --color-background: hsl(220, 13%, 10%);
    --color-surface: hsl(220, 13%, 15%);
    --color-surface-elevated: hsl(220, 13%, 18%);
    --color-border: hsl(220, 13%, 23%);

    /* Text (inverted) */
    --color-text: hsl(220, 9%, 93%);
    --color-text-secondary: hsl(220, 9%, 70%);
    --color-text-muted: hsl(220, 9%, 55%);

    /* Adjust saturation for dark mode */
    --color-primary: hsl(220, 80%, 60%);
    --color-success: hsl(142, 70%, 45%);
    --color-error: hsl(0, 80%, 65%);

    /* Shadows in dark mode need adjustment */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
  }
}

Dark mode principles: - Reduce saturation on large surfaces - Increase lightness of accent colors - Strengthen shadows (they need more contrast) - Design dark mode intentionally, not as an afterthought


Figma Extraction Workflows

Transforming design files into production code requires systematic extraction of design tokens—colors, typography, spacing, and effects that define your design language.

Figma Variables Export

Figma’s native Variables feature provides the cleanest extraction path:

Export Steps: 1. Open Figma file → Local Variables panel 2. Click collection menu → “Export to JSON” 3. Save as figma-variables.json

JSON Token Structure:

{
  "colors": {
    "primitive": {
      "blue-500": { "value": "#3b82f6", "type": "color" },
      "blue-600": { "value": "#2563eb", "type": "color" }
    },
    "semantic": {
      "primary": { "value": "{colors.primitive.blue-500}", "type": "color" },
      "primary-hover": { "value": "{colors.primitive.blue-600}", "type": "color" }
    }
  },
  "spacing": {
    "1": { "value": "4px", "type": "spacing" },
    "2": { "value": "8px", "type": "spacing" },
    "4": { "value": "16px", "type": "spacing" }
  }
}

Token-to-CSS Transformation

CSS Custom Properties:

:root {
  /* Primitive colors (direct values) */
  --color-blue-50: #eff6ff;
  --color-blue-100: #dbeafe;
  --color-blue-500: #3b82f6;
  --color-blue-600: #2563eb;
  --color-blue-900: #1e3a8a;

  /* Semantic colors (reference primitives) */
  --color-primary: var(--color-blue-500);
  --color-primary-hover: var(--color-blue-600);
  --color-background: var(--color-white);
  --color-surface: var(--color-gray-50);

  /* Spacing (8px grid) */
  --space-1: 0.25rem;  /* 4px */
  --space-2: 0.5rem;   /* 8px */
  --space-4: 1rem;     /* 16px */
  --space-6: 1.5rem;   /* 24px */
  --space-8: 2rem;     /* 32px */

  /* Typography */
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.125rem;
  --line-height-tight: 1.25;
  --line-height-normal: 1.5;

  /* Effects */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
}

Dark Mode Tokens:

@media (prefers-color-scheme: dark) {
  :root {
    --color-background: var(--color-gray-900);
    --color-surface: var(--color-gray-800);
    --color-text: var(--color-gray-100);
    --color-text-secondary: var(--color-gray-400);

    /* Adjusted shadows for dark mode */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
  }
}

Token-to-SwiftUI Transformation

Color Extension:

import SwiftUI

extension Color {
    // MARK: - Primitive Colors
    static let blue50 = Color(hex: "eff6ff")
    static let blue500 = Color(hex: "3b82f6")
    static let blue600 = Color(hex: "2563eb")

    // MARK: - Semantic Colors
    static let brandPrimary = Color.blue500
    static let brandPrimaryHover = Color.blue600

    // MARK: - Surface Colors
    static let surfaceBackground = Color(light: .white, dark: Color(hex: "0f172a"))
    static let surfaceElevated = Color(light: Color(hex: "f8fafc"), dark: Color(hex: "1e293b"))
}

extension Color {
    init(hex: String) {
        // Standard hex parsing implementation
    }

    init(light: Color, dark: Color) {
        self.init(UIColor { traits in
            traits.userInterfaceStyle == .dark ? UIColor(dark) : UIColor(light)
        })
    }
}

Spacing Constants:

enum Spacing {
    static let xs: CGFloat = 4    // --space-1
    static let sm: CGFloat = 8    // --space-2
    static let md: CGFloat = 16   // --space-4
    static let lg: CGFloat = 24   // --space-6
    static let xl: CGFloat = 32   // --space-8
}

// Usage
VStack(spacing: Spacing.md) {
    // ...
}
.padding(Spacing.lg)

Designer Handoff Checklist

What Designers Should Export:

Asset Type Format Notes
Colors Variables JSON Include light + dark modes
Typography Styles export Font, size, weight, line-height
Spacing Variables JSON Base unit documented
Icons SVG Outlined, single color
Images PNG @2x/@3x or WebP With compression
Components Figma links For reference during implementation

Quality Gate Criteria:

  • [ ] All colors defined as variables (no hardcoded hex)
  • [ ] Typography uses defined text styles
  • [ ] Spacing follows grid system (8px base)
  • [ ] Dark mode variants provided
  • [ ] Interactive states documented (hover, active, disabled)
  • [ ] Responsive breakpoints annotated
  • [ ] Accessibility requirements noted (contrast ratios)

Developer Receives:

  1. Token files (JSON/CSS/Swift depending on platform)
  2. Component specs with measurements
  3. Asset exports in required formats
  4. Interaction documentation (states, animations)
  5. Accessibility annotations

Quick Reference Tables

Gestalt Principles

Principle Rule Use
Proximity Related = close Forms, sections
Similarity Same look = same function Buttons, cards
Figure-Ground Clear layer separation Modals, cards
Continuity Follow lines Timelines, alignment
Closure Brain completes shapes Icons, scroll hints

Typography

Element Size Weight Line Height
Body 16px 400 1.5-1.7
Headlines 24-48px 600-700 1.1-1.2
UI Labels 12-14px 500 1.3-1.4
Captions 12px 400 1.4

Color Roles

Role Light Mode Dark Mode
Background #ffffff #0f172a
Surface #f4f5f7 #1e293b
Border #e4e6ea #334155
Text #1a1a2e #f1f5f9
Text Muted #6b7280 #94a3b8
Primary #3b82f6 #60a5fa
Success #22c55e #4ade80
Error #ef4444 #f87171

Spacing Scale

Token Value Use
–space-1 4px Icon gaps
–space-2 8px Inline elements
–space-4 16px Default gaps
–space-6 24px Card padding
–space-8 32px Section gaps
–space-16 64px Page sections

Design Checklist

Before shipping any interface, verify:

Gestalt

  • [ ] Related elements are closer than unrelated ones (Proximity)
  • [ ] Similar functions have similar styles (Similarity)
  • [ ] Clear separation between foreground and background (Figure-Ground)
  • [ ] Eye flows naturally through layout (Continuity)

Typography

  • [ ] Base font size is at least 16px
  • [ ] Line height is 1.5+ for body text
  • [ ] Line length is under 75 characters
  • [ ] Hierarchy is clear (3 levels distinguishable)
  • [ ] Consistent scale used throughout

Color

  • [ ] All text passes 4.5:1 contrast (WCAG AA)
  • [ ] Color is not the only indicator (icons/labels too)
  • [ ] Dark mode designed intentionally
  • [ ] 60-30-10 distribution followed

Visual Hierarchy

  • [ ] Can identify the #1 most important element
  • [ ] Eye flows in intended order
  • [ ] One clear CTA per section
  • [ ] Type scale consistent

Spacing

  • [ ] All spacing uses defined scale (no magic numbers)
  • [ ] Cards/components have consistent padding
  • [ ] Mobile spacing is comfortable
  • [ ] Grid alignment is consistent (8px base)

Dieter Rams Check

  • [ ] Can anything be removed?
  • [ ] Does every element serve function?
  • [ ] Would this feel dated in 5 years?
  • [ ] Have I designed every state?

Resources

Books: - As Little Design as Possible by Sophie Lovell (Dieter Rams) - The Elements of Typographic Style by Robert Bringhurst

Tools: - WebAIM Contrast Checker - Type Scale Generator - Figma Tokens Studio — Design token management

Design Systems: - Apple HIG - Material Design 3 - Radix UI - shadcn/ui


Design Studies

Deep dives into 16 exceptional products, documenting patterns and principles worth stealing.

Developer Tools

Product Key Contribution
Figma Multiplayer presence, context-aware panels
Warp Block-based terminal, CLI-GUI bridge
Framer Visual responsive design, property controls
Vercel Dark mode excellence, ambient status
Linear Optimistic UI, keyboard-first workflow
Raycast Extension system, quick actions

iOS Native (Apple Design Award Winners)

Product Key Contribution
Flighty 15 smart states, Live Activities, data visualization
Halide Intelligent activation, gesture controls
Bear Typography-first, inline tagging
Craft Native-first cross-platform, nested pages
Things Deferred dates, quick entry patterns

Productivity & AI

Product Key Contribution
Superhuman 100ms rule, command palette training, practice onboarding
Perplexity Citation-forward AI, streaming phases
Notion Block system, slash commands
Arc Spaces, split view, command bar
Stripe Documentation excellence, API design

This guide grows through practice. Design principles are timeless, but their application evolves with technology and understanding.