Spruce CSS comes with a bunch of Sass variables and generates CSS custom properties.

List of Colors

You can access the following colors through Spruce’s $colors map by default. You can also use the color() helper function to access the colors.

Shared

black $color-black
danger $color-danger
danger $color-danger
gray $color-gray
gray light $color-gray-light
primary $color-primary
secondary $color-secondary
success $color-success
white $color-white

Alert

danger $color-danger
info hsl(195deg 100% 42%)
success $color-success
warning hsl(48deg 89% 55%)

Base

background $color-white
blockquote-border $color-primary
border $color-gray-light
code-background color.change($color-primary, $lightness: 97%)
code-foreground $color-black
heading $color-black
link $color-primary
link-hover color.scale($color-primary, $lightness: -20%)
mark-background hsl(50deg 100% 80%)
mark-foreground $color-black
marker $color-primary
primary $color-primary
secondary $color-secondary
strong $color-black
text $color-gray

Btn (Button)

primary-background $color-primary
primary-background-hover color.adjust($color-primary, $lightness: -10%)
primary-foreground $color-white
primary-shadow color.adjust($color-primary, $lightness: 35%)
secondary-background $color-secondary
secondary-background-hover color.adjust($color-secondary, $lightness: -10%)
secondary-foreground $color-white
secondary-shadow color.adjust($color-secondary, $lightness: 35%)

Form

background $color-white
background-disabled hsl(0deg 0% 95%)
border hsl(260deg 4% 70%)
border-disabled $color-gray-light
border-focus $color-primary
check-background $color-primary
check-focus-ring $color-primary
check-foreground $color-white
group-label-background hsl(210deg 60% 98%)
group-label-foreground $color-gray
invalid $color-danger
invalid-focus-ring color.adjust($color-danger, $alpha: -0.75)
label $color-black
legend $color-black
placeholder hsl(208deg 7% 40%)
range-thumb-background $color-primary
range-thumb-focus-ring $color-primary
range-track-background $color-gray-light
ring-focus color.adjust($color-primary, $alpha: -0.75)
select-foreground $color-black
text $color-gray
valid $color-success
valid-focus-ring color.adjust($color-success, $alpha: -0.75)

Selection

foreground $color-white
background $color-primary

Scrollbar

thumb-background hsl(0deg 0% 0% / 15%)
thumb-background-hover hsl(0deg 0% 0% / 25%)
track-background hsl(0deg 0% 0% / 5%)

Table

border $color-gray-light
caption $color-gray
heading $color-black
hover hsl(0deg 0% 0% / 5%)
stripe hsl(0deg 0% 0% / 2.5%)
text $color-gray

Shared Colors

We store the color values in a central map named $colors. It is a nested object separated by components.

To eliminate the repetition, we use some helper variables for the more generic colors (which we use more than once). You can overwrite these directly to make the theming easier or from the object one by one.

@use 'sprucecss/scss/spruce' with (
  $color-black: hsl(205deg 100% 2%),
  $color-danger: hsl(0deg 71% 51%),
  $color-gray: hsl(208deg 9% 42%),
  $color-gray-light: hsl(215deg 63% 93%),
  $color-primary: hsl(262deg 71% 49%),
  $color-secondary: hsl(227deg 92% 55%),
  $color-success: hsl(150deg 100% 33%),
  $color-white: hsl(0deg 0% 100%),
);

Customize Colors

Below is the full declaration of the $colors map.

@use 'sprucecss/scss/spruce' with (
  $colors: (
    'alert': (
      'danger': $color-danger,
      'info': hsl(195deg 100% 42%),
      'success': $color-success,
      'warning': hsl(48deg 89% 55%),
    ),
    'base': (
      'background': $color-white,
      'blockquote-border': $color-primary,
      'border': $color-gray-light,
      'code-background': color.change($color-primary, $lightness: 97%),
      'code-foreground': $color-black,
      'heading': $color-black,
      'link': $color-primary,
      'link-hover': color.scale($color-primary, $lightness: -20%),
      'mark-background': hsl(50deg 100% 80%),
      'mark-foreground': $color-black,
      'marker': $color-primary,
      'primary': $color-primary,
      'secondary': $color-secondary,
      'strong': $color-black,
      'text': $color-gray,
    ),
    'btn': (
      'primary-background': $color-primary,
      'primary-background-hover': color.adjust($color-primary, $lightness: -10%),
      'primary-foreground': $color-white,
      'primary-shadow': color.adjust($color-primary, $lightness: 35%),
      'secondary-background': $color-secondary,
      'secondary-background-hover': color.adjust($color-secondary, $lightness: -10%),
      'secondary-foreground': $color-white,
      'secondary-shadow': color.adjust($color-secondary, $lightness: 35%),
    ),
    'form': (
      'background': $color-white,
      'background-disabled': hsl(0deg 0% 95%),
      'border': hsl(260deg 4% 70%),
      'border-disabled': $color-gray-light,
      'border-focus': $color-primary,
      'check-background': $color-primary,
      'check-focus-ring': $color-primary,
      'check-foreground': $color-white,
      'group-label-background': hsl(210deg 60% 98%),
      'group-label-foreground': $color-gray,
      'invalid': $color-danger,
      'invalid-focus-ring': color.adjust($color-danger, $alpha: -0.75),
      'label': $color-black,
      'legend': $color-black,
      'placeholder': hsl(208deg 7% 40%),
      'range-thumb-background': $color-primary,
      'range-thumb-focus-ring': $color-primary,
      'range-track-background': $color-gray-light,
      'ring-focus': color.adjust($color-primary, $alpha: -0.75),
      'select-foreground': $color-black,
      'text': $color-gray,
      'valid': $color-success,
      'valid-focus-ring': color.adjust($color-success, $alpha: -0.75),
    ),
    'selection': (
      'foreground': $color-white,
      'background': $color-primary,
    ),
    'scrollbar': (
      'thumb-background': hsl(0deg 0% 0% / 15%),
      'thumb-background-hover': hsl(0deg 0% 0% / 25%),
      'track-background': hsl(0deg 0% 0% / 5%),
    ),
    'table': (
      'border': $color-gray-light,
      'caption': $color-gray,
      'heading': $color-black,
      'hover': hsl(0deg 0% 0% / 5%),
      'stripe': hsl(0deg 0% 0% / 2.5%),
      'text': $color-gray,
    ),
  );
);

We declare the colors with the modern HSL syntax. The generated values are given and converted by Sass by default.

Get Color Values

Spruce generates prefixed CSS variables at :root by group from the nested map above.

You can always access a generated variable by name, but it is easier to use the custom getter function named color().

a {
  color: color('primary');
}

.control {
  background-color: color('primary-background', 'btn');
}

Overwrite, Add New Color

Because the colors are in a Sass map, it is easy to overwrite them or add new values, blocks.

@use 'sprucecss/scss/spruce' with (
  $colors: (
    'base': (
      'primary': hsl(0 0% 15%),
      'tertiary': hsl(332deg 49% 29%),
    ),
    'my-custom-component': (
      'background': hsl(0deg 0% 100%),
    ),
  ),
);

Dark Colors

Spruce CSS supports dark-mode, which we mainly achieve through CSS Custom Properties. You can use the $dark-colors map to set up your dark colors.

$dark-colors: ();

List Colors

In this example, you can see how you can generate a component - an alert - using Spruce’s colors with Sass’s @each and map.get.

@use 'sass:color';
@use 'sass:map';
@use 'sprucecss/scss/spruce' as *;

.alert {
  border: 1px solid;
  border-left: 0.35rem solid;
  border-radius: config('border-radius-lg', $display);
  font-weight: 500;
  gap: spacer('m');
  justify-content: space-between;
  padding: 0.65em 1em;

  @each $name, $value in map.get($colors, 'alert') {
    @at-root .alert--#{$name} {
      background-color: color.scale($value, $lightness: 90%);
      color: color.scale($value, $lightness: -30%);
    }
  }
}