4 min read
Theming
Modern apps support light and dark modes. This guide covers how to implement theme systems and handle system preference detection.
System Preference Detection
How it works
- Operating systems expose light/dark preference
- Apps can read and respond to this setting
- Preference can change while app is running
Web: prefers-color-scheme
@media (prefers-color-scheme: dark) {
/* dark mode styles */
}
SwiftUI: colorScheme
.preferredColorScheme()modifier@Environment(\.colorScheme)to read current- Automatic with semantic colors
Prompting for system detection
Detect the system color scheme preference.
Default to the user's system setting but allow
manual override.
Color Scheme Architecture
Semantic color naming
Instead of literal colors, use semantic names:
backgroundnotwhitetext-primarynotblacksurfacenotgray-100accentnotblue-500
Color pairs
Each semantic color needs light and dark values:
background:
light: #FFFFFF
dark: #121212
text-primary:
light: #1A1A1A
dark: #F5F5F5
surface:
light: #F5F5F5
dark: #1E1E1E
Beyond black and white
- True black (#000) can be harsh in dark mode
- Off-black (#121212) is easier on the eyes
- Consider reduced contrast for less important text
- Accent colors may need different values per theme
Design Token Approach
Setting up tokens
Set up a theme system with these tokens:
Light theme:
- Background: #FFFFFF
- Surface: #F8FAFC
- Text: #1E293B
- Accent: #2563EB
Dark theme:
- Background: #0F172A
- Surface: #1E293B
- Text: #F1F5F9
- Accent: #3B82F6
CSS custom properties (Web)
:root {
--bg: #ffffff;
--text: #1a1a1a;
}
[data-theme="dark"] {
--bg: #121212;
--text: #f5f5f5;
}
SwiftUI Color assets
- Create color sets in Assets.xcassets
- Define “Any Appearance” and “Dark” variants
- Reference by name:
Color("background")
Theme Switching
User preference storage
- Save user choice (system/light/dark)
- Persist across sessions
- Default to system preference
Implementation prompts
Add a theme toggle in settings.
Options: System (default), Light, Dark.
Save the preference so it persists.
Smooth transitions
Add a smooth transition when switching themes.
The colors should fade, not snap instantly.
Manual override
Let users override the system setting.
Add a three-way toggle: Light / System / Dark
Platform-Specific Patterns
Web
- CSS custom properties for colors
data-themeattribute on html/body- JavaScript for toggle and persistence
- Prefers-color-scheme media query for default
SwiftUI
- Asset catalog color sets
@Environment(\.colorScheme)preferredColorScheme()modifier- Automatic with semantic system colors
React Native
- Appearance module for system detection
- Context for app-wide theme
- Styled-components or emotion for dynamic theming
Beyond Light/Dark
Multiple themes
- Brand themes
- High contrast mode
- Seasonal themes
- User-customizable themes
High contrast
Add a high contrast mode option.
Increase the contrast ratios beyond standard.
Accent color customization
Let users choose their accent color from
a set of preset options.
Testing Themes
What to check
- All text remains readable
- Interactive elements are distinguishable
- Images and icons adapt appropriately
- No hard-coded colors leaking through
Testing prompts
Switch to dark mode. Check that all
components adapt correctly and nothing
uses hard-coded light colors.
Edge cases
- Images on backgrounds (may need borders)
- Charts and data visualizations
- Third-party embeds
- User-generated content
Example Prompts
Basic dark mode
Add dark mode support. Use semantic colors
that adapt to the system preference.
Theme toggle
Add a theme toggle in the header.
It should cycle through: light, dark, system.
Show an icon for the current mode.
Smooth transitions
When the theme changes, animate the color
transition over 200ms so it's not jarring.
Custom accent color
Let users pick an accent color for the app.
Offer 6 preset colors. Save their choice.
Complete theme system
Set up a complete theme system:
- Light and dark modes
- System preference detection
- Manual override with persistence
- Semantic color tokens
- Smooth transitions when switching
What You’ll Learn
- How to detect system color preferences
- Semantic color naming approaches
- Design token architecture for themes
- Implementing theme switchers
- Testing across different modes