DEV Community

SwiftUI Dark Mode: The Complete Implementation Guide

Dark Mode is no longer optional — users expect it. Here's how to implement it properly in SwiftUI.

The Basics: Color Scheme

SwiftUI provides @Environment(\.colorScheme) to detect the current mode:

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        Text("Hello")
            .foregroundColor(colorScheme == .dark ? .white : .black)
    }
}
Enter fullscreen mode Exit fullscreen mode

But there's a better way...

Use Semantic Colors

SwiftUI has built-in colors that adapt automatically:

Text("Adapts automatically")
    .foregroundColor(.primary)      // Black in light, white in dark
    .background(Color(.systemBackground))  // White in light, black in dark
Enter fullscreen mode Exit fullscreen mode

Key semantic colors:

  • .primary / .secondary — text colors
  • Color(.systemBackground) — main background
  • Color(.secondarySystemBackground) — grouped content

Create a Theme System

For full control, create a theme:

struct AppTheme {
    let background: Color
    let text: Color
    let accent: Color

    static let light = AppTheme(
        background: .white,
        text: .black,
        accent: .blue
    )

    static let dark = AppTheme(
        background: Color(.systemGray6),
        text: .white,
        accent: .cyan
    )
}
Enter fullscreen mode Exit fullscreen mode

Use it with environment:

struct ThemeKey: EnvironmentKey {
    static let defaultValue = AppTheme.light
}

extension EnvironmentValues {
    var theme: AppTheme {
        get { self[ThemeKey.self] }
        set { self[ThemeKey.self] = newValue }
    }
}
Enter fullscreen mode Exit fullscreen mode

Preview Both Modes

Always test both modes in previews:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
                .preferredColorScheme(.light)
            ContentView()
                .preferredColorScheme(.dark)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Common Mistakes

  1. Hardcoding colors — Use semantic colors instead
  2. Forgetting images — Use SF Symbols or provide dark variants
  3. Not testing — Always preview both modes

Skip the Setup

If you want Dark Mode already configured with a complete theme system, check out SwiftUI Starter Kit Pro. It includes a production-ready theme with automatic dark mode support.


Questions? Drop them below!

Follow @SwiftUIDaily for daily SwiftUI tips.

Top comments (0)