New in v3: design styles, dark mode, blocks and pages
A minimalistic, low-level CSS framework
A low-level, lightweight and modern CSS system, authoring tool built on Sass. Give your project a solid foundation.
main.scss
// 1. Configure Spruce once, before anything else uses it.
@use 'config/config';
// 2. The base: normalize, typography, forms, dark mode and style presets.
@use 'config/fonts';
@use 'config/styles';
// 3. Your own code, written with Spruce's tokens.
@use 'component';
@use 'block';<!DOCTYPE html>
<html lang="en" data-theme-mode="dark" data-spruce-style="brand">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Acme</title>
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
<section class="hero-block">
<div class="container">
<div class="hero-block__inner">
<h1 class="hero-block__title">Ship your next idea</h1>
<p class="hero-block__lead">One stylesheet, eight looks.</p>
<div class="hero-block__actions">
<a class="btn btn--primary btn--lg" href="/start">Get started</a>
<a class="btn btn--outline-primary btn--lg" href="/docs">Read the docs</a>
</div>
</div>
</div>
</section>
<!-- Scope a style to one part of the page -->
<article class="card" data-spruce-style="editorial">
<h2 class="card__title"><a href="/blog/v3">Spruce CSS v3</a></h2>
<p class="card__text">Styles, dark mode, AI skills.</p>
</article>
</body>
</html>@use 'brand-style' as brand;
@use 'sprucecss/scss/spruce' with (
$settings: (
'css-custom-properties': true,
'dark-mode': (
'prefers-color-scheme': true,
),
'styles': (
'include': ('brand', 'minimal', 'editorial'),
),
),
$generators: (
'content': (
'dark-mode': true,
'styles': true,
),
),
$colors: (
'base': (
'primary': hsl(262deg 71% 49%),
),
),
$dark-colors: (
'base': (
'primary': hsl(262deg 90% 72%),
),
),
$typography: (
'font-family-base': #{'Inter', sans-serif},
'font-family-heading': #{'Manrope', sans-serif},
),
$styles: (
'brand': brand.$style,
),
);// A custom design style: tokens, colors and a few rules.
$style: (
'label': 'Brand',
'description': 'Rounded, warm and a little bold.',
'tokens': (
'radius-sm': 0.5rem,
'radius-lg': 1.5rem,
'btn-padding': 0.8em 1.5em,
'shadow-md': 0 10px 30px hsl(262deg 60% 30% / 15%),
),
'colors': (
'base': (
'background': hsl(40deg 60% 98%),
'primary': hsl(14deg 90% 52%),
),
),
'dark-colors': (
'base': (
'background': hsl(20deg 15% 9%),
'primary': hsl(14deg 95% 64%),
),
),
'rules': (
'h1, h2': (
'letter-spacing': -0.03em,
),
),
);@use 'sprucecss/scss/spruce' as *;
@include font-face('Inter', '../font/inter-regular.woff2');
@include font-face('Inter', '../font/inter-600.woff2', 600);
@include font-face('Manrope', '../font/manrope-700.woff2', 700);
@include font-face('Manrope', '../font/manrope-800.woff2', 800);@use 'sprucecss/scss/spruce' as *;
// Normalize, typography, forms, buttons, layout,
// the dark mode and the style presets in one call.
@include generate-styles;@forward 'card';
@forward 'header';@use 'sprucecss/scss/spruce' as *;
.card {
@include a11y-card-link('.card__title a', true);
@include layout-stack('xs');
@include transition($property: 'box-shadow, translate');
background-color: color('surface');
border: config('border-width-base', $display) solid color('border');
border-radius: radius('lg');
box-shadow: shadow('sm');
padding: spacer-clamp('m', 'l');
&:hover {
box-shadow: shadow('lg');
}
@include motion-safe {
&:hover {
translate: 0 -0.25rem;
}
}
&:focus-within {
@include focus-ring($ring-color: color('focus-ring'));
}
&__title {
font-size: font-size('h4');
margin-block: 0;
a {
color: color('heading');
text-decoration: none;
}
}
&__text {
color: color('muted');
margin-block: 0;
}
}@use 'sprucecss/scss/spruce' as *;
.site-header {
backdrop-filter: blur(12px);
background-color: color-alpha('background', 0.85);
border-block-end: config('border-width-base', $display) solid color('border');
inset-block-start: 0;
position: sticky;
z-index: z-index('sticky');
&__inner {
@include layout-cluster('m');
justify-content: space-between;
min-block-size: 4.5rem;
}
&__menu {
@include clear-list;
display: none;
gap: spacer('m');
@include breakpoint('md') {
display: flex;
}
}
&__link[aria-current='page'] {
color: color('primary');
font-weight: 700;
}
}@forward 'hero';@use 'sprucecss/scss/spruce' as *;
// .hero-block > .container > .hero-block__inner
.hero-block {
background-image: radial-gradient(
circle at 50% 0,
color-alpha('primary', 0.15),
transparent 60%
);
padding-block: spacer-clamp('xl', 'xxl');
&__inner {
@include layout-stack('m');
align-items: center;
margin-inline: auto;
max-inline-size: 48rem;
text-align: center;
}
&__title {
font-size: responsive-font-size(4rem, 40);
margin-block: 0;
}
&__lead {
color: color('muted');
font-size: font-size('h5');
}
&__actions {
@include layout-cluster('s');
justify-content: center;
}
@include dark-mode {
background-image: radial-gradient(
circle at 50% 0,
color-alpha('primary', 0.3),
transparent 60%
);
}
}The entry point: configure Spruce first, then generate the base and load your own code.
Installation


Blocks and Pages
Full-width page blocks and complete page templates, ready to copy.
Good to Know
Spruce CSS in nutshell.