Skip to content

Sass: Variables Default Values

How to use the !default flag in Sass to create configurable library variables that preserve user-defined values while providing fallbacks.

Normally when you assign a value to a variable, if that variable already had a value, its old value is overwritten.

Default Values

But if you're writing a Sass library, you might want to allow your users to configure your library's variables before you use them to generate CSS.

To make this possible, Sass provides the !default flag. This assigns a value to a variable only if that variable isn't defined or its value is null. Otherwise, the existing value will be used.

How !default works

Scenario Variable state before Assignment Final value
Not defined $foo: bar !default; bar
Already defined $foo: baz; $foo: bar !default; baz (keeps existing)
Defined as null $foo: null; $foo: bar !default; bar (null is treated as undefined)
$width: 100px;
$width: 200px !default;  // Keeps 100px
$height: null;
$height: 50px !default;   // Becomes 50px
$color: blue !default;    // Becomes blue

Configuring Modules

Variables defined with !default can be configured when loading a module with the @use rule. Sass libraries often use !default variables to allow their users to configure the library's CSS.

To load a module with configuration, write @use <url> with (<variable>: <value>, <variable>: <value>). The configured values will override the variables' default values. Only variables written at the top level of the stylesheet with a !default flag can be configured.

// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;

code {
  border-radius: $border-radius;
  box-shadow: $box-shadow;
}
// style.scss
@use 'library' with (
  $black: #222,
  $border-radius: 0.1rem
);

The compiled CSS uses the user's overrides:

code {
  border-radius: 0.1rem;
  box-shadow: 0 0.5rem 1rem rgba(#222, 0.15);
}

Library pattern: _variables.scss

A common convention in Sass libraries is to place all configurable variables in a dedicated partial, then import it first so users can override them before any CSS is generated:

// _variables.scss
$primary-color: #036 !default;
$font-stack: Helvetica, Arial, sans-serif !default;
$base-spacing: 1rem !default;
// _components.scss
@use 'variables';

.button {
  background-color: variables.$primary-color;
  font-family: variables.$font-stack;
  padding: variables.$base-spacing;
}
// user-style.scss
@use 'variables' with (
  $primary-color: purple,
  $font-stack: Georgia, serif
);
@use 'components';

!default with @forward

When you @forward a module, its !default variables can still be configured by downstream users, as long as they are defined at the top level of the forwarded file:

// _library.scss
$spacing: 1rem !default;
// _index.scss
@forward 'library';
// user-style.scss
@use 'index' with ($spacing: 2rem);

Summary

  • !default assigns a value only if the variable is undefined or null.
  • Use !default for library variables that users should be able to override.
  • Configure !default variables with @use <url> with (<var>: <value>, ...).
  • Only top-level variables with !default can be configured via @use ... with.
  • Common pattern: put !default variables in a dedicated partial and import it first.
Navigation