SwiftUI Dark Mode: The Complete Implementation Guide

Published: (January 31, 2026 at 01:37 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

Detecting the Current Color Scheme

SwiftUI provides @Environment(\.colorScheme) to detect whether the app is in light or dark mode.

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

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

Using Adaptive Colors

Instead of manually checking the color scheme, you can rely on SwiftUI’s built‑in adaptive colors.

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

Key Semantic Colors

  • .primary / .secondary – text colors that adapt automatically.
  • Color(.systemBackground) – main background color.
  • Color(.secondarySystemBackground) – background for grouped content.

Creating a Custom Theme

For full control over colors, define a theme structure.

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
    )
}

Providing the Theme via Environment

Define an EnvironmentKey and extend EnvironmentValues to store the current theme.

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

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

Previewing Both Modes

Always test your UI in both light and dark appearances.

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
                .preferredColorScheme(.light)

            ContentView()
                .preferredColorScheme(.dark)
        }
    }
}

Common Pitfalls

  • Hard‑coding colors – Prefer semantic colors (.primary, .secondary, system background colors) that adapt automatically.
  • Missing image assets – Provide dark‑mode variants or use SF Symbols, which adapt by default.
  • Skipping previews – Always preview both light and dark schemes to catch visual issues early.
Back to Blog

Related posts

Read more »

[SUI] Barra de búsqueda

Barra de búsqueda en NavigationStack Un NavigationStack puede incluir una barra de búsqueda mediante el modificador searchable. Su firma es: swift searchable t...

SwiftUI Isn't Slow — Your Code Is

SwiftUI Rendering: What’s Fast and What’s Slow SwiftUI’s rendering engine is fast. What slows it down is the work you ask it to redo hundreds of times per seco...