Themes

Themes let you customize the appearance of your site, with built-in support for light and dark modes.

Creating themes

Themes conform to the Theme protocol, which provides sensible defaults for both light and dark appearances. When creating a theme, you specify its colorScheme to determine whether it uses light or dark variants of Ignite’s default styles.

struct MyTheme: Theme {
    var colorScheme: ColorScheme = .light // or .dark
    
    // Override any theme properties you want to customize
    var syntaxHighlighterTheme: HighlighterTheme = .githubLight
}

Theme composition

You can create a base theme protocol that provides common values for multiple themes. This allows you to share styling between themes while still having color scheme specific values for properties you haven’t explicitly set.

// Base protocol with shared theme values
protocol BaseTheme: Theme {}

// Default implementation for shared values
extension BaseTheme {
    var accent: Color { Color(hex: "#FF0000") }
    var secondaryAccent: Color { Color(hex: "#00FF00") }
}

// Light theme implementation
struct LightTheme: BaseTheme {
    var colorScheme: ColorScheme = .light
    // Uses shared accent/secondaryAccent colors
    // Other values default to stock light theme colors
}

// Dark theme implementation
struct DarkTheme: BaseTheme {
    var colorScheme: ColorScheme = .dark
    // Uses shared accent/secondaryAccent colors
    // Other values default to stock dark theme colors
}

To enable themes in your site, add them to your site configuration:

struct ExampleSite: Site {
    var lightTheme: (any Theme)? = LightTheme()
    var darkTheme: (any Theme)? = DarkTheme()
    var alternateThemes: [any Theme] = [
        SeaTheme(),
        DesertTheme(),
        ForestTheme()
    ]
}

Note: You can add additional themes through Site’s alternateThemes property.

You can disable either light or dark mode by setting the corresponding theme to nil:

struct DarkOnlySite: Site {
    var lightTheme: (any Theme)? = nil  // Disable light mode
    var darkTheme: (any Theme)? = DarkTheme()
}

struct LightOnlySite: Site {
    var lightTheme: (any Theme)? = LightTheme()
    var darkTheme: (any Theme)? = nil   // Disable dark mode
}

Note: You must provide at least one theme (either light or dark). Setting both lightTheme and darkTheme to nil will result in a build error.

Theme switching

You can access all available themes through the environment, making it easy to create a theme switcher. The SwitchTheme() action lets users change themes dynamically.

struct ThemeSwitcher: HTML {
    @Environment(\.themes) private var themes

    var body: some HTML {
        ForEach(themes) { theme in
            Button(theme.name) {
                SwitchTheme(theme)
            }
        }
    }
}

Give the theme switcher at the bottom of this page a whirl to see this all in action. 👇

Materials

When using Material, the correct variant (light or dark) will automatically be selected based on your theme’s colorScheme value.

You can override the default Material variant using the colorScheme() method, which is useful when you want components to always use a specific appearance:

ZStack {
    Image("/images/photos/dishwasher.jpg")
        .resizable()
    Text("Always Dark Material")
        .font(.title3)
        .containerRelativeFrame()
        .background(.thinMaterial.colorScheme(.dark))
}
.clipped()
.cornerRadius(12)

Here’s an example using Material:

Adaptive Material

Always Dark Material

Created in Swift with Ignite

Ignite v0.5.2 · Updated 22/04/25