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, but it’s recommended to use either LightTheme or DarkTheme as your base – these provide sensible defaults matching Bootstrap’s light and dark themes respectively.

struct MyLightTheme: LightTheme {
    static var name: String = "light"
    var syntaxHighlighterTheme: HighlighterTheme = .xcodeLight
}

struct MyDarkTheme: DarkTheme {
    static var name: String = "dark"
    var syntaxHighlighterTheme: HighlighterTheme = .xcodeDark
}

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

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

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

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 whether your theme conforms to LightTheme or DarkTheme.

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)
        .frame(maxWidth: .percent(100%), maxHeight: .percent(100%))
        .background(.thinMaterial.colorScheme(.dark))
}
.clipped()
.cornerRadius(12)

Here’s an example using Material:

Adaptive Material

Always Dark Material

Created in Swift with Ignite