Sass Reference - - By Hugo Giraudel

Variables

Variables are the essence of any programming language. When you think about it, it is quite horrifying that CSS awaited 17 years before coming up with a specification draft about native variables (actually custom properties). That being said, this long term gap has been one of the reasons that led people into building CSS preprocessors. Sass, I believe, has been providing variables since day one although their syntax and the way they work has changed over the year.

A variable, broadly speaking, is a storage location paired with an associated identifier (a.k.a a variable name). When applied to Sass, it basically gives the ability to store little bites of content so they can be reused throughout stylesheets. This comes in especially handy for colors, only to avoid having countless variations of the same color after a couple of months working on the same project. It can also be helpful to store other types of content such as list of fonts, maps of breakpoints, default asset path, and so on.

Scope

Variables can be defined absolutely anywhere in a document, however depending on its position, its access might be restricted to a specific code block; this is what we call a scope. Sass has always honored the idea of scopes, meaning a variable defined within a mixin, a function or a ruleset is local by default. This also means that a global variable and a local variable can share the same name seamlessly: the local will be restricted to its own scope, while the global one will be accessible from anywhere in the document.

Sass official documentation talks about global variable shadowing. When declaring a variable that already exists on the global scope in an inner scope (such as a function), the local variable is said to be shadowing the global one.

The following code snippet should explain the variable shadowing concept quite clearly:

// Initialize a global variable at root-level of the document
$variable: 'initial value';

// Create a mixin that overrides that global variable
@mixin global-variable-overriding {
  $variable: 'mixin value' !global;
}

.foo {
  // Create a local variable that shadows the global one
  $variable: 'local value';

  // Include the mixin: it overrides the global variable
  @include global-variable-overriding;

  // Print the variable's value
  // It is the local one, since it shadows the global one
  // Meanwhile the global variable has been correctly updated
  content: $variable;
}

// Print the variable in another selector that does no shadowing.
// It is the global one, as expected.
.bar {
  content: $variable;
}

Global flag

The global flag (!global) is used when overwriting a global variable from a local scope. For instance, when updating a global configuration from a mixin or a function, the variable assignment has to use the global flag; else, it will simply create a new local variable.

$variable: 0;

// Here, global `$variable` is not updated
// Instead a local `$variable` is created
.foo {
    $variable: 1;
    content: $variable; // 1
}

// This time, global `$variable` is updated
.bar {
    content: $variable; // 0
    $variable: 3 !global;
}

.baz {
    content: $variable; // 3
}

When defining a variable at the root of a document, you do not have to use !global and you should not use it in such circumstances. Indeed, this is an abuse of !global that might make the code confusing. On top of that, Sass is likely to prevent the usage of !global on a root-level variable assignment in a future version.

Default flag

The default flag (!default) can be used to assign to a variable if and only if it is not already assigned. If the variable already exists, it won’t be updated and if it does not have a value yet, it will be given one.

This is invaluable for external libraries and frameworks providing a handful of variables for configuration. When importing the project, variables are set to their default values and can be safely re-assigned after or even before the import as long as they have been initially set up with the default flag.

$variable: 0;
$variable: 1 !default;
// 0

$variable: 0 !default;
$variable: 1;
// 1

$variable: 0 !default;
$variable: 1 !default;
// 0

Example

$main-color: #BADA55;

.foo {
  color: $main-color;
}

.bar {
  background: $main-color;
}

Engine compatibility

Variables are fully compatible across all Sass engines and there is no known bug to this day about their implementation. However note that prior to Sass 3.4, a variable assignment in a scope while a global variable with the same name existed already would overwrite the global one. From Sass 3.4, this behaviour is no longer true as any variable assignment is local, unless using the !global flag.