Spruce CSS v3 has a complete dark mode built in. This guide shows the whole setup: colors, detection and the details that colors alone don't cover.
It builds on the project configuration structure.
scss/
├── config/
│ ├── _index.scss
│ ├── _config.scss
│ ├── _dark-colors.scss
│ ├── _dark-mode.scss
│ └── _styles.scss
└── main.scssThe default dark palette works out of the box. Override only what you need in _dark-colors.scss, with the same structure as the $colors map:
$colors: (
'base': (
'background': hsl(222deg 47% 8%),
'primary': hsl(199deg 89% 60%),
),
'btn': (
'primary-background': hsl(199deg 89% 48%),
'primary-background-hover': hsl(199deg 89% 55%),
),
);In _config.scss, pass the colors and enable the dark-mode generator:
@use 'dark-colors' as dark;
@use 'sprucecss/scss/spruce' with (
$dark-colors: dark.$colors,
$generators: (
'content': ('dark-mode': true),
),
$settings: (
'dark-mode': (
'prefers-color-scheme': true, // optional: follow the system
),
),
);The generator outputs the dark custom properties under :root[data-theme-mode="dark"], sets color-scheme: dark and regenerates the SVG icons of the form elements.
Some things need more than new colors: a different image, a softer shadow, a logo. Keep them in _dark-mode.scss with the dark-mode mixin:
@use 'sprucecss/scss/spruce' as *;
@include dark-mode {
.hero {
background-image: url('../img/hero-dark.webp');
}
}
.card {
box-shadow: shadow('md');
@include dark-mode {
box-shadow: none;
}
}Set data-theme-mode="dark" on the <html> element. The Build a Theme Switcher guide shows a complete, flash-free switcher with system detection.
The v2 approach (generate-color-variables($dark-colors, ':root[data-theme-mode="dark"]') plus the regenerated select icon) still works. Replace it with the generator to get the complete default palette and all the form icons.


