SASS/SCSS

Variables: Defining & Using

20 min Lesson 4 of 30

Variables: Defining & Using

Variables are one of the most fundamental and powerful features of SASS. They allow you to store values and reuse them throughout your stylesheets, making your code more maintainable, consistent, and easier to update. In this comprehensive lesson, we'll explore everything about SASS variables - from basic syntax to advanced techniques.

The $ Syntax for Variables

In SASS, all variables start with a dollar sign ($). This makes them instantly recognizable and prevents naming conflicts with CSS properties.

Basic Variable Syntax

// Variable declaration
$variable-name: value;

// Variable usage
selector {
  property: $variable-name;
}

Here's a simple example:

Simple Variable Example

$primary-color: #3498db;

.button {
  background-color: $primary-color;
}

.link {
  color: $primary-color;
}

Compiled CSS

.button {
  background-color: #3498db;
}

.link {
  color: #3498db;
}
Note: Variable names are case-sensitive. $primary-color and $Primary-Color are different variables!

Variable Data Types

SASS variables can store different types of data. Understanding these types helps you use variables effectively.

1. Numbers

Numbers can be integers or decimals, with or without units:

Number Variables

$font-size: 16px;          // Number with unit
$line-height: 1.6;         // Unitless number
$width: 100%;              // Percentage
$padding: 2rem;            // rem unit
$opacity: 0.8;             // Decimal
$z-index: 100;             // Integer

.element {
  font-size: $font-size;
  line-height: $line-height;
  width: $width;
  padding: $padding;
  opacity: $opacity;
  z-index: $z-index;
}

2. Strings

Strings can be quoted or unquoted:

String Variables

$font-family: 'Helvetica Neue', Arial, sans-serif;  // Quoted
$direction: left;                                     // Unquoted
$content: "Hello World";                              // Double quotes

.element {
  font-family: $font-family;
  text-align: $direction;
  content: $content;
}
Tip: Use single quotes for font families and strings in SCSS. Use unquoted strings for CSS keywords like left, center, bold, etc.

3. Colors

Colors can be in any CSS color format:

Color Variables

$color-hex: #3498db;                    // Hex
$color-rgb: rgb(52, 152, 219);          // RGB
$color-rgba: rgba(52, 152, 219, 0.8);   // RGBA
$color-hsl: hsl(204, 70%, 53%);         // HSL
$color-named: red;                      // Named color

.element {
  background: $color-hex;
  border-color: $color-rgb;
  color: $color-rgba;
  box-shadow: 0 0 10px $color-hsl;
  outline-color: $color-named;
}

4. Booleans

Boolean values are true or false, often used with control directives (@if):

Boolean Variables

$enable-shadows: true;
$enable-rounded: false;

.card {
  @if $enable-shadows {
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  }

  @if $enable-rounded {
    border-radius: 8px;
  }
}

5. Null

The null value represents no value. Properties with null values are omitted from CSS output:

Null Variables

$border-width: null;

.element {
  border-width: $border-width;  // This line won't appear in CSS
  border-style: solid;           // This will appear
}

Compiled CSS

.element {
  border-style: solid;
}

6. Lists

Lists are sequences of values separated by spaces or commas:

List Variables

// Space-separated list
$padding-values: 10px 20px 15px 20px;

// Comma-separated list
$font-stack: 'Helvetica Neue', Arial, sans-serif;

// Mixed list
$box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.05);

.element {
  padding: $padding-values;
  font-family: $font-stack;
  box-shadow: $box-shadow;
}

7. Maps

Maps are key-value pairs (like objects in JavaScript):

Map Variables

$colors: (
  primary: #3498db,
  secondary: #2ecc71,
  danger: #e74c3c,
  warning: #f39c12
);

// Access map values with map-get()
.button-primary {
  background: map-get($colors, primary);
}

.button-danger {
  background: map-get($colors, danger);
}
Tip: Maps are incredibly powerful for organizing related values like color palettes, breakpoints, or z-index scales. We'll explore maps in depth in a later lesson!

Variable Scope: Global vs Local

Understanding variable scope is crucial for writing maintainable SASS code. SASS has two types of scope:

Global Scope

Variables declared outside any selector or block are global and can be accessed anywhere:

Global Variables

// Global variable
$primary-color: #3498db;

.header {
  background: $primary-color;  // Works!
}

.button {
  background: $primary-color;  // Works!
}

.footer {
  background: $primary-color;  // Works!
}

Local Scope

Variables declared inside a selector are local to that selector and cannot be accessed outside:

Local Variables

.header {
  $header-height: 80px;        // Local variable
  height: $header-height;      // Works!
}

.main {
  margin-top: $header-height;  // ERROR! Variable undefined
}
Warning: Trying to use a local variable outside its scope will cause a compilation error: "Undefined variable."

Shadowing Global Variables

You can create a local variable with the same name as a global variable. The local variable "shadows" the global one within its scope:

Variable Shadowing

$color: blue;        // Global

.header {
  $color: red;       // Local (shadows global)
  background: $color;  // Uses red (local)
}

.footer {
  background: $color;  // Uses blue (global)
}

Compiled CSS

.header {
  background: red;
}

.footer {
  background: blue;
}

The !default Flag: Optional Overrides

The !default flag assigns a value to a variable only if that variable is not already defined. This is incredibly useful for creating library defaults that users can override:

Using !default

// User defines their preference
$primary-color: #e74c3c;

// Library sets default (will be ignored because variable already defined)
$primary-color: #3498db !default;

.button {
  background: $primary-color;  // Uses #e74c3c (user's value)
}

If the user doesn't define the variable, the default is used:

!default When Variable Not Defined

// User doesn't define anything

// Library sets default (will be used)
$primary-color: #3498db !default;

.button {
  background: $primary-color;  // Uses #3498db (default)
}
Tip: Always use !default when creating reusable SASS libraries or design systems. It allows users to customize without modifying your source code!

The !global Flag: Creating Globals from Local Scope

The !global flag allows you to create or modify a global variable from within a local scope:

Using !global

.header {
  $header-height: 80px !global;  // Creates global variable
  height: $header-height;
}

.main {
  margin-top: $header-height;  // Works! Variable is global now
}
Warning: Use !global sparingly! It can make code harder to understand and debug. Prefer declaring global variables at the top of your file.

Variable Naming Conventions

Good variable names make your code self-documenting and maintainable. Follow these conventions:

Use Kebab-Case

Good Variable Names

$primary-color: #3498db;
$font-size-base: 16px;
$border-radius-small: 4px;
$box-shadow-large: 0 10px 20px rgba(0, 0, 0, 0.2);

Bad Variable Names

$primaryColor: #3498db;      // camelCase (not standard in CSS)
$primary_color: #3498db;     // snake_case (not standard in CSS)
$pc: #3498db;                // Too short/unclear
$blue: #3498db;              // Too generic

Be Descriptive

Variable names should describe their purpose or usage, not just their value:

Descriptive Names (Good)

$color-primary: #3498db;
$color-success: #2ecc71;
$color-danger: #e74c3c;
$font-family-heading: 'Georgia', serif;
$spacing-unit: 8px;

Value-Based Names (Avoid)

$blue: #3498db;              // What if brand color changes to green?
$green: #2ecc71;
$red: #e74c3c;
$georgia: 'Georgia', serif;
$eight: 8px;
Tip: Use semantic names (purpose-based) over presentational names (appearance-based). If your "blue" button needs to become green, you don't want to have $blue: green; in your code!

Common Use Cases for Variables

Let's explore practical, real-world use cases for SASS variables:

1. Color Palettes

Color System

// Brand colors
$color-primary: #3498db;
$color-secondary: #2ecc71;
$color-accent: #f39c12;

// Semantic colors
$color-success: #2ecc71;
$color-warning: #f39c12;
$color-danger: #e74c3c;
$color-info: #3498db;

// Neutral colors
$color-white: #ffffff;
$color-gray-100: #f8f9fa;
$color-gray-200: #e9ecef;
$color-gray-300: #dee2e6;
$color-gray-900: #212529;
$color-black: #000000;

// Text colors
$color-text-primary: $color-gray-900;
$color-text-secondary: $color-gray-300;
$color-text-muted: $color-gray-200;

2. Typography System

Typography Variables

// Font families
$font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
$font-family-heading: 'Georgia', 'Times New Roman', serif;
$font-family-code: 'Monaco', 'Courier New', monospace;

// Font sizes
$font-size-base: 16px;
$font-size-small: 14px;
$font-size-large: 18px;
$font-size-h1: 32px;
$font-size-h2: 28px;
$font-size-h3: 24px;

// Font weights
$font-weight-light: 300;
$font-weight-normal: 400;
$font-weight-semibold: 600;
$font-weight-bold: 700;

// Line heights
$line-height-tight: 1.2;
$line-height-base: 1.6;
$line-height-loose: 1.8;

3. Spacing Scale

Spacing System

$spacing-unit: 8px;

$spacing-xs: $spacing-unit * 0.5;     // 4px
$spacing-sm: $spacing-unit;            // 8px
$spacing-md: $spacing-unit * 2;        // 16px
$spacing-lg: $spacing-unit * 3;        // 24px
$spacing-xl: $spacing-unit * 4;        // 32px
$spacing-2xl: $spacing-unit * 6;       // 48px
$spacing-3xl: $spacing-unit * 8;       // 64px

.card {
  padding: $spacing-md;
  margin-bottom: $spacing-lg;
}

.section {
  padding-top: $spacing-2xl;
  padding-bottom: $spacing-2xl;
}

4. Breakpoints for Responsive Design

Breakpoint Variables

$breakpoint-mobile: 480px;
$breakpoint-tablet: 768px;
$breakpoint-desktop: 1024px;
$breakpoint-wide: 1280px;

.container {
  width: 100%;

  @media (min-width: $breakpoint-tablet) {
    max-width: 720px;
  }

  @media (min-width: $breakpoint-desktop) {
    max-width: 960px;
  }

  @media (min-width: $breakpoint-wide) {
    max-width: 1200px;
  }
}

5. Z-Index Scale

Z-Index System

$z-index-dropdown: 1000;
$z-index-sticky: 1020;
$z-index-fixed: 1030;
$z-index-modal-backdrop: 1040;
$z-index-modal: 1050;
$z-index-popover: 1060;
$z-index-tooltip: 1070;

.modal {
  z-index: $z-index-modal;
}

.tooltip {
  z-index: $z-index-tooltip;
}
Tip: Centralizing z-index values prevents the infamous "z-index: 999999" problem where developers keep adding 9s to ensure their element is on top!

Variables vs CSS Custom Properties

CSS now has native variables called Custom Properties. How do they compare to SASS variables?

SASS Variables

  • Compiled at build time
  • Static - cannot change at runtime
  • Support all SASS features (functions, operations, etc.)
  • Work in all browsers (compiled to plain CSS)
  • More features: data types, maps, functions

CSS Custom Properties

  • Evaluated at runtime in the browser
  • Dynamic - can change with JavaScript
  • Cascade and inherit like normal CSS
  • Can be scoped to specific elements
  • Limited to modern browsers (but widely supported now)

Comparing Both

// SASS Variable
$primary: #3498db;

// CSS Custom Property
:root {
  --primary: #3498db;
}

.element {
  // Using SASS variable
  background: $primary;

  // Using CSS Custom Property
  color: var(--primary);
}
Tip: Use both together! SASS variables for build-time configuration and CSS Custom Properties for runtime theming and dynamic values. Many modern projects use SASS to generate CSS Custom Properties!

Practical Example: Complete Variable System

Let's put it all together with a real-world example:

_variables.scss

// ===========================================
// Color System
// ===========================================

$color-primary: #3498db !default;
$color-secondary: #2ecc71 !default;
$color-danger: #e74c3c !default;

// ===========================================
// Typography
// ===========================================

$font-family-base: -apple-system, BlinkMacSystemFont, sans-serif !default;
$font-size-base: 16px !default;
$line-height-base: 1.6 !default;

// ===========================================
// Spacing
// ===========================================

$spacing-unit: 8px !default;
$spacing-small: $spacing-unit !default;
$spacing-medium: $spacing-unit * 2 !default;
$spacing-large: $spacing-unit * 3 !default;

// ===========================================
// Components
// ===========================================

$border-radius: 4px !default;
$box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !default;
$transition-speed: 0.3s !default;

// ===========================================
// Breakpoints
// ===========================================

$breakpoint-tablet: 768px !default;
$breakpoint-desktop: 1024px !default;

Conclusion

Variables are the foundation of maintainable SASS code. You've learned about data types, scope, the !default and !global flags, naming conventions, and practical use cases. With this knowledge, you can create consistent, scalable design systems!

In the next lesson, we'll explore nesting in detail - both selector nesting and property nesting - and learn best practices to avoid common pitfalls.

Exercise 1: Create a Color Palette

Create a comprehensive color system:

  1. Define 3 brand colors (primary, secondary, accent)
  2. Define 4 semantic colors (success, warning, danger, info)
  3. Create a grayscale with at least 5 shades
  4. Use these variables to style a button component with different states
  5. Compile and test in HTML

Exercise 2: Typography System

Build a complete typography system:

  1. Define variables for font families (base, heading, code)
  2. Create a modular scale with 5 font sizes
  3. Define font weights (light, normal, bold)
  4. Define line heights (tight, base, loose)
  5. Apply to HTML headings and paragraphs

Exercise 3: Experiment with Scope

Practice variable scope:

  1. Create a global $color variable
  2. In one selector, shadow it with a local variable of the same name
  3. In another selector, try to access a local variable from the first selector (it should fail)
  4. Use !global to create a global variable from within a selector
  5. Document what you learn about when each approach is useful