3.10 — Color psychology & palette design

Opening scenario

You’re a solo dev building a finance app. You pick “vibrant orange and electric purple” because they’re your favorite colors. You ship. Users on Reddit say it looks “like a toy” and “unprofessional.” Your install-to-account-link conversion is 12%. You repaint to charcoal + navy blue. Conversion jumps to 31%. Same product, same code — the color told users to trust you.

Color is not decoration. It’s a signal of category, trustworthiness, and emotional register. This chapter teaches the patterns: which palettes work for which app categories, how to compose them with the 60-30-10 rule, how to verify them with contrast tools, and how to ship them to iOS with light/dark variants.

ColorCommon associations
BlueTrust, stability, professionalism (banks, healthcare, productivity)
GreenGrowth, money, health (finance, fitness, nature)
RedUrgency, food, passion, danger (food delivery, sports, alerts)
OrangeEnergy, friendliness, retail (consumer, kids, coupons)
PurpleCreativity, luxury, beauty (cosmetics, music, kids)
PinkFemininity, youth, dating (dating, gen-Z, kids)
Black/GrayPremium, minimalist, fashion (luxury, photography, dev tools)
YellowOptimism, attention, warning (children’s, alerts)

These are not universal — culture matters — but they’re the dominant Western/US/EU mappings, which is what App Review and the App Store algorithm evaluate.

Concept → Why → How → Code

Color by app category

A defensible palette starts with category research. Open the App Store, search your category, screenshot the top 20 apps. Note their primary brand color. Patterns:

  • Finance / Banking: Cash App (green), Robinhood (green), Chase (blue), Bank of America (red+blue), Venmo (blue), PayPal (blue), Stripe (purple). Trust signals dominate; saturated brand color over neutral surface.
  • Health / Fitness: MyFitnessPal (blue), Strava (orange), Apple Fitness (red+orange gradient), Headspace (orange + gradient). Energy and warmth; often a vibrant secondary accent.
  • Entertainment / Streaming: Netflix (red), Spotify (green), HBO (purple/black), Disney+ (blue-black), Twitch (purple). Dark backgrounds + saturated brand — let content shine, frame it with confidence.
  • Productivity: Notion (white+black), Linear (purple+black), Things (blue), Reminders (orange), Asana (orange+pink). Restrained, often near-monochrome with one accent.
  • Social / Dating: Tinder (red/pink), Bumble (yellow), Hinge (red), Instagram (gradient pink-purple-orange). Saturated, warm, playful.
  • Kids / Education: Duolingo (green), Khan Academy (green), Lego (yellow+red+blue), Toca Boca (rainbow). Primary colors, high saturation, playful.
  • Travel / Maps: Airbnb (coral-red), Booking (blue+yellow), Google Maps (white+colored), Lyft (pink). Welcoming, often with one bold accent.

The exercise: when designing a new app, list 5 competitors → screenshot → find the median palette. Stay within ±20° on the color wheel from the median unless you have a defensible reason. Going too far signals “different” but often reads as “wrong category.”

The 60-30-10 rule

A balanced palette uses:

  • 60% — dominant color (usually a neutral or background)
  • 30% — secondary color (supporting surfaces, secondary actions)
  • 10% — accent color (primary actions, brand emphasis)

In a SwiftUI app:

ZStack {
    Color(.systemBackground)         // 60% — most of the screen
    VStack {
        Card()                       // 30% — secondary surface
            .background(Color(.secondarySystemBackground))
        Button("Buy") { … }          // 10% — accent (the brand color)
            .buttonStyle(.borderedProminent)
    }
}

Apps that violate this — 60% bright brand color — feel exhausting after 30 seconds. The eye needs rest space.

Apple’s semantic system as the 60-30

Color(.systemBackground), Color(.secondarySystemBackground), Color(.tertiarySystemBackground) already do the 60-30 for you. You just add the 10% accent:

// In your App or root view
.tint(.brandPrimary)

// Now every Button, Toggle, NavigationLink, ProgressView, etc.
// uses brandPrimary as its accent — automatically.

.tint(_:) is the single most powerful color modifier in SwiftUI. Set it once at the top, get a consistent accent everywhere. No per-component overrides.

Tools for picking palettes

When you’re not just picking a single brand color, use these:

  • Coolors.co — generate 5-color palettes, lock favorites, regenerate. Free, fast, great for ideation.
  • Adobe Color — color wheel with harmony rules (analogous, triadic, complementary, monochrome). Best for understanding why a palette feels balanced.
  • Color Hunt — curated palettes by category. Browse the “Pastel” or “Dark” sections to spark ideas.
  • Contrast — Mac app, menu bar utility, pick two pixels → instant WCAG ratio.
  • Realtime Colors — paste a palette, see it applied to a sample app UI live. Best “does this work?” tool.
  • uiGradients — for picking gradient pairs.

The workflow: Coolors for ideation → Adobe Color to verify harmony → Realtime Colors to preview on a UI → Contrast to verify WCAG.

The Apple semantic palette (re-stated as a checklist)

Every app needs at least these semantic colors, defined in Asset Catalog with Light/Dark variants:

// Brand
brandPrimary       // your main brand color
brandSecondary     // accent / link

// Surfaces (or use Apple's systemBackground family)
surfacePrimary     // page background
surfaceSecondary   // card / sheet background
surfaceTertiary    // inset / grouped background

// Content (or use Apple's label family)
contentPrimary     // body text
contentSecondary   // secondary text
contentTertiary    // disabled / placeholder

// Semantic state
success            // green
warning            // yellow / orange
error              // red
info               // blue

That’s 10-12 colors. Most successful apps fit in this set. More colors = more drift, more inconsistency, more decisions per screen.

Dark mode color pairs

Dark mode is not “invert” — it’s a separate palette tuned for low-light viewing. Rules of thumb:

Light modeDark mode equivalent
Pure white background #FFFFFFNear-black #0A0A0A or #1C1C1E (Apple’s systemBackground) — never pure black
Pure black text #000000Off-white #F2F2F7 (Apple’s label)
Vibrant accent at 100% saturationSame accent at ~85% saturation (less aggressive on dark)
Subtle shadowSubtle glow / lighter border

Why not pure black in dark mode? OLED display “smearing” — pure black next to bright content causes ghosting. Apple uses #1C1C1E.

Setup in Asset Catalog:

  1. New Color Set → “brandPrimary”
  2. Attributes Inspector → Appearances: Any, Dark
  3. Set Any (light mode) to your brand color
  4. Set Dark to the desaturated/adjusted version
  5. Reference: Color(.brandPrimary) or generated Color.brandPrimary

Same color name, two values, automatic adaptation.

WCAG contrast checking

For every text-on-background combination in your palette:

  • Body text on background: ≥ 4.5:1
  • Large text (≥ 18pt or ≥14pt bold) on background: ≥ 3:1
  • UI components (icons, borders): ≥ 3:1

If your brand color is light (yellow, light blue, pink), it likely fails 4.5:1 against white. Solutions:

  • Use brand color only on large or bold text
  • Use brand color only as background with white/dark text on top
  • Use brand color only for icons and accents, never body text

Check every pair. The Contrast app makes this 2-second work.

App icon color strategy

Your app icon is your most-viewed color choice. Patterns:

  • Solid brand color, white glyph: Spotify, Cash App, Robinhood. Simple, recognizable at every size.
  • Gradient brand: Instagram, Apple Health, Apple Fitness. Eye-catching but harder to read at 60×60.
  • Photographic / detailed: Bear, Threes! Art-feels but loses detail at small sizes.
  • Two-color flat: Apple Notes (yellow lines on white), Apple Music (pink-red gradient). Tested at every size.

Test your icon at the actual sizes: 60×60 (iPhone home screen), 76×76 (iPad), 120×120 (retina spotlight), 1024×1024 (App Store). Apple’s Icon Composer tool renders all sizes; preview before shipping.

For iOS 26 Liquid Glass (introduced WWDC25), provide a “Tinted” icon variant (system tints your icon to user’s wallpaper) and a “Dark” variant.

Avoiding palette drift in code

Once defined, the palette must not drift. Enforce:

  1. SwiftLint custom rule: ban Color(red:), Color(hex:), Color(white:). Force Color.brandPrimary style.
  2. Generated asset symbols (Xcode 15+): Color(.brandPrimary) is compile-checked.
  3. PR template checkbox: “If you added a color, did you add it to the design tokens module?”
  4. Quarterly audit: grep -rn "Color(" --include="*.swift" — anything not from tokens gets fixed.

In the wild

  • Stripe uses purple as a distinctive payment-app color (in a sea of blue) — successful differentiation within finance. Their site and docs are case studies in restrained palette use.
  • Linear’s palette: near-monochrome (gray scale) plus one signature purple. 95% of the UI is neutral; the purple is reserved for active states. Studied widely in design system communities.
  • Duolingo’s green: paired with a friendly typography and Duo’s voice, it signals “approachable learning.” If they’d picked navy, it would feel like an enterprise LMS. Brand color choice is product strategy.
  • Cash App rebranded from green to black-and-green in 2018; conversion analytics showed the more sophisticated palette converted higher-value users.
  • Twitter → X color change from blue to black caused widespread brand-recognition drop (well documented in marketing case studies). Color is brand equity.

Common misconceptions

  1. “My favorite color should be the brand color.” Rarely. Brand color should match category and target user, not founder preference.
  2. “More colors = more energy = better.” No. Restraint is a marker of professional design. Most great apps use 3-5 colors total.
  3. “Dark mode is just inverted light mode.” Wrong — different colors entirely, especially desaturated accents.
  4. “WCAG AA contrast is too restrictive for cool designs.” Inaccessible cool designs are bad designs. AA is achievable with creativity; AAA is hard but AA is non-negotiable.
  5. “Color psychology is pseudoscience.” The cultural mappings (red = food, blue = trust in Western markets) are empirically supported in consumer behavior research. The individual-mood claims (yellow makes you happy) are weak. Use the category data, ignore the rest.

Seasoned engineer’s take

For new apps, the order of operations on color:

  1. Category research — screenshot 20 competitors, find the median palette
  2. Pick a primary brand color — within ±30° of category median unless you have a defensible reason
  3. Generate complementary palette — Coolors or Adobe Color for harmony
  4. Verify WCAG contrast — Contrast app
  5. Define dark mode pairs — desaturate brand, near-black bg
  6. Define semantic tokensbrandPrimary, surface, content, success/warning/error/info
  7. Wire .tint() at App root — every accent gets the brand color for free
  8. Test in Realtime Colors — paste palette, preview on mock UI
  9. Add to Asset Catalog with light/dark + high-contrast appearances
  10. Lint to prevent drift

Spend a day on this once. The palette will outlive 90% of your code.

TIP: Always build a “color audit” screen in your app — a screen that shows every color token, light + dark, with WCAG ratios. Saves you from a future “is this still our brand color?” question. Keep it in a #if DEBUG build configuration.

WARNING: Don’t ship colors directly from Coolors palettes without WCAG checking. Trendy palettes from Coolors often fail contrast for body text. Verify.

Interview corner

Junior-level: “How would you pick a color palette for a new app?”

Research competitors in the category. Pick a primary brand color aligned with category expectations. Use a tool like Coolors or Adobe Color to generate complementary supporting colors. Verify WCAG contrast for all text/background pairs. Define light and dark variants in Asset Catalog.

Mid-level: “What’s the 60-30-10 rule and why does it matter?”

60% dominant (usually neutral background), 30% secondary (surfaces), 10% accent (brand). It prevents palette overload, gives the eye rest space, and ensures the brand color is special (not exhausting). Apple’s semantic colors already do the 60-30; you add the 10% via .tint().

Senior-level: “Design a color system that works across iOS, watchOS, macOS, and Apple Vision Pro for a single brand.”

Define brand primary + 2-3 brand accents at the primitive token level. Define semantic tokens (surface, content, state) per platform — watchOS uses near-black backgrounds, macOS supports more saturated colors (larger surface area), visionOS prefers translucent materials. Single source in Figma variables → Tokens Studio export → Style Dictionary → generates platform-specific token files. CI ensures sync. App-level .tint() ties it all together. Verify WCAG on every platform; visionOS has unique contrast requirements with translucent backgrounds.

Red flag in candidates: Picking colors based purely on aesthetics with no category research, no contrast check, no semantic naming. Tells you they haven’t shipped a product that needed to convert.

Lab preview

You’ll derive a full palette from a one-sentence brief in Lab 3.3 — Palette from Brief.


Phase 3 chapters complete. The labs apply everything: