Sass Variables

Beginner
⏱️ 15 min read
📚 Updated: Jul 2026
🎯 5 Examples
$name: value

What You’ll Learn

Sass variables store values under $names. This page covers declarations, Sass vs CSS variables, scope, !default, !global, maps instead of dynamic names, and five compiled examples.

01

Declare

$name:

02

vs CSS

Compile-time

03

Scope

Global / local

04

!default

Configure libs

05

!global

Update outer

06

Practice

5 examples

What Are Sass Variables?

Official docs: assign a value to a name that begins with $, then refer to that name instead of repeating the value. Variables reduce repetition, enable math and theming, and help configure libraries.

A declaration looks like a property ($name: value;) but can appear almost anywhere—not only inside style rules.

  • Compiled away—the CSS file contains the final values, not $names.
  • Imperative: using a variable snapshots its current value.
  • Hyphens and underscores are equivalent ($font-size = $font_size).
  • Cannot invent variable names with interpolation—use a map instead.
💡
Beginner tip

Start with a small set of brand tokens ($brand, $space, $radius) at the top of a file or module, then build everything else from them.

📝 Syntax

styles.scss
$base-color: #c6538c;
$border-dark: rgba($base-color, 0.88);

.alert {
  border: 1px solid $border-dark;
}

⚖️ Sass Variables vs CSS Variables

Official docs: CSS has its own variables (--token), and they are totally different from Sass $variables.

Sass $varCSS --var
Compiled awayKept in the CSS output
One value at a timeCan differ per element
Imperative (earlier uses keep old value)Declarative (later changes can affect uses)

⚡ Default Values (!default)

Official docs: normally a new assignment overwrites the old value. With !default, Sass assigns only if the variable is undefined or null. Libraries use this so consumers can configure tokens first.

With @use, you can also configure module defaults: @use "library" with ($black: #222);

🏢 Scope, Shadowing & !global

  • Top-level variables are global within their module.
  • Inside blocks (rules, mixins, …) variables are usually local.
  • Shadowing — a local $name can hide a global one without changing it.
  • !global — assign to the existing top-level variable from inside a block.
💡
Heads up

Modern Dart Sass only allows !global on variables already declared at the top level—it cannot create a brand-new global from inside a block.

Flow control scope: variables inside @if / loops do not shadow outer variables at the same level—they assign to them. Declare the variable first (even as null) before conditionally updating it.

🧮 Built-ins & Dynamic Names

Variables from built-in modules (like math.$pi) cannot be reassigned. For “dynamic variable names,” store values in a map and look them up with map.get—Sass does not allow $theme-#{$name} style declarations.

Helpers such as meta.variable-exists() and meta.global-variable-exists() can inspect the current or global scope when needed.

⚡ Quick Reference

GoalCode
Declare$brand: #036;
Usecolor: $brand;
Default if unset$brand: #036 !default;
Set global from block$brand: #000 !global;
Configure a module@use "lib" with ($brand: #222);
Dynamic keysmap.get($theme, "warning")

Examples Gallery

Each example shows a core variable behavior. Open View Compiled CSS for verified output.

📚 Getting Started

Declare, reuse, and see how reassignment works over time.

Example 1 — Declare and Reuse

Official-docs style: derive a border color from a base brand color.

styles.scss
$base-color: #c6538c;
$border-dark: rgba($base-color, 0.88);

.alert {
  border: 1px solid $border-dark;
}

How It Works

Change $base-color once and every derived token that uses it updates at compile time. No $ names remain in the CSS.

Example 2 — Imperative Values (Earlier Uses Stick)

Reassigning later does not rewrite earlier rules that already used the variable.

styles.scss
$variable: value 1;
.rule-1 {
  value: $variable;
}

$variable: value 2;
.rule-2 {
  value: $variable;
}

How It Works

Each use captures the value at that moment. This is the opposite of CSS custom properties, which are declarative.

📈 Scope, Globals & Configuration

Local shadowing, !global updates, !default, and map tokens.

Example 3 — Global vs Local Scope

Top-level variables are visible later; block variables stay inside their block.

styles.scss
$global-variable: global value;

.content {
  $local-variable: local value;
  global: $global-variable;
  local: $local-variable;
}

.sidebar {
  global: $global-variable;
  // $local-variable is not available here
}

How It Works

$local-variable never leaks into .sidebar. That prevents accidental cross-rule coupling.

Example 4 — Update a Global with !global

Assign inside a rule, but write to the existing top-level variable.

styles.scss
$variable: first global value;

.content {
  $variable: second global value !global;
  value: $variable;
}

.sidebar {
  value: $variable;
}

How It Works

Without !global, the inner assignment would only shadow. With it, both rules see the updated global value.

Example 5 — !default, Flow Control & Maps

Configure theme colors, adjust them in @if, and look up tokens from a map.

styles.scss
@use "sass:color";
@use "sass:map";

$dark-theme: true !default;
$primary-color: #f8bbd0 !default;
$accent-color: #6a1b9a !default;

@if $dark-theme {
  $primary-color: color.scale($primary-color, $lightness: -60%);
  $accent-color: color.scale($accent-color, $lightness: 60%);
}

$theme-colors: (
  "success": #28a745,
  "info": #17a2b8,
  "warning": #ffc107,
);

$font_size: 16px;
$font-size: 18px; // same variable as $font_size

.button {
  background-color: $primary-color;
  border: 1px solid $accent-color;
  border-radius: 3px;
}

.alert {
  background-color: map.get($theme-colors, "warning");
}

.size {
  font-size: $font-size;
}

How It Works

!default keeps earlier user settings. The @if block updates the outer theme variables. The map avoids illegal dynamic $theme-#{} names. Hyphen/underscore aliases share one variable.

🚀 Real-World Use Cases

  • Design tokens — brand colors, spacing, radii, fonts.
  • Library configuration!default + @use … with.
  • Theming — toggle flags then adjust related variables.
  • DRY math — compute derived sizes from one base unit.
  • Named palettes — maps when keys must be dynamic.

🧠 How Compilation Works

1

Declare / configure

Set $names, optionally with !default or @use with.

Define
2

Resolve each use

Substitute the current value in scope (imperative snapshot).

Use
3

Maybe reassign

Later assignments affect only later uses unless !global.

Update
4

CSS ships

Only concrete values remain—no $variables in the file.

⚠️ Common Pitfalls

  • Confusing with CSS --vars — Sass variables do not cascade in the browser.
  • Expecting earlier rules to update — reassignment is imperative.
  • Accidental locals — assigning inside a block without !global shadows.
  • Dynamic $name-#{} — not allowed; use a map.
  • Using !global to create new globals — declare at top level first.

💡 Best Practices

✅ Do

  • Keep shared tokens at the module top level
  • Use !default for library-configurable settings
  • Prefer maps for families of related named values
  • Name variables by meaning ($brand, not $blue2)
  • Combine Sass tokens with CSS variables when runtime theming is needed

❌ Don’t

  • Scatter magic numbers that should be tokens
  • Assume CSS var(--x) rules apply to $x
  • Build variable names with interpolation
  • Overwrite globals from deep nests without !global on purpose
  • Forget that hyphens and underscores share one name

Key Takeaways

Knowledge Unlocked

Five things to remember about Sass variables

$names, compile-time values, scope, and safe configuration.

5
Core concepts
⚙️ 02

Compile-time

not in CSS

Stage
🏢 03

Scope

global / local

Rules
04

!default

configure libs

API
05

Maps

dynamic keys

Pattern

❓ Frequently Asked Questions

Names that start with $ and hold a value. You declare $name: value; then use $name anywhere that value is allowed.
Sass variables are compiled away and have one value at a time (imperative). CSS custom properties stay in the CSS and can differ per element (declarative).
It assigns a value only if the variable is undefined or null. Libraries use it so users can configure values before the library runs.
It assigns to the global variable from inside a local block. The global variable must already exist at the top level.
No. Sass treats hyphens and underscores as the same in identifiers, so both names refer to one variable.
No. Use a map and map.get() when you need dynamic names, instead of $theme-#{$name}.
Did you know?

Official Sass docs note that hyphens and underscores are treated as identical in variable names—a historical compatibility detail from when Sass only allowed underscores.

Conclusion

Sass variables are compile-time $names for reusable values. Master scope, !default for libraries, and maps for dynamic keys—and remember they are not the same as CSS custom properties.

Continue with Sass Comments or Sass Numbers.

Next: Sass Comments

Learn silent //, loud /* */, and /*! important comments.

Sass Comments →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful