Sass Maps — Complete Guide
In this tutorial, you will learn about Sass Maps. We cover key concepts, practical examples, and best practices to help you master this topic.
Sass maps store key-value pairs for structured configuration using sass:map module with functions for access, merge, iteration, and deep nesting.
What You'll Learn
- Creating and accessing maps
- Map manipulation (merge, remove, keys, values)
- Deep/nested maps
- Iterating maps with @each
- Using maps for themes, breakpoints, and configuration
- Functions that work with maps for lookup
Why It Matters
- Maps provide structured data like JavaScript objects
- Centralized configuration reduces scatter
- Maps enable dynamic theme generation
- Nested maps model complex design tokens
Real-World Use
- A breakpoint map drives all responsive queries
- A theme map contains all design tokens
- A variant map generates component styles
- A z-index map centralizes layering
flowchart LR A[Sass Maps] --> B[Keys] A --> C[Values] B --> D[map-get, map-keys] C --> E[map-values, map-has-key] A --> F[Iteration] F --> G[Generate CSS from data]
Working with Maps
Code Example: Creating and Accessing Maps
@use 'sass:map';
// Basic map
$breakpoints: (
'sm': 480px,
'md': 768px,
'lg': 1024px,
'xl': 1280px
);
// Accessing values
$md-width: map.get($breakpoints, 'md'); // 768px
$lg-width: map.get($breakpoints, 'lg'); // 1024px
// Check if key exists
$has-sm: map.has-key($breakpoints, 'sm'); // true
$has-xxl: map.has-key($breakpoints, 'xxl'); // false
// Get all keys or values
$keys: map.keys($breakpoints); // 'sm', 'md', 'lg', 'xl'
$values: map.values($breakpoints); // 480px, 768px, 1024px, 1280px
// Count entries
$count: map.length($breakpoints); // 4
// Using map values
@function bp($name) {
@if map.has-key($breakpoints, $name) {
@return map.get($breakpoints, $name);
} @else {
@error "Unknown breakpoint: #{$name}.";
}
}
.container {
max-width: bp('lg') - 40px; // 984px
}
@media (min-width: bp('md')) {
.sidebar { width: 300px; }
}
Expected output: map.get() retrieves values by key. map.has-key() checks existence. map.keys() and map.values() extract all keys or values. The bp() function provides a clean lookup API.
Code Example: Map Manipulation
@use 'sass:map';
// Merge maps
$default-theme: (
'primary': #0066CC,
'secondary': #6c757d,
'font-size': 16px
);
$dark-overrides: (
'primary': #4da6ff,
'bg': #1a1a2e,
'text': #e0e0e0
);
$dark-theme: map.merge($default-theme, $dark-overrides);
// Result: (primary: #4da6ff, secondary: #6c757d, font-size: 16px, bg: #1a1a2e, text: #e0e0e0)
// Note: $dark-overrides keys overwrite $default-theme keys
// Merge with deep merge (for nested maps)
$shallow: map.merge($default-theme, $dark-overrides); // Shallow merge
$deep: map.deep-merge($default-theme, $dark-overrides); // Deep merge (recursive)
// Remove keys
$reduced: map.remove($default-theme, 'secondary');
// Result: (primary: #0066CC, font-size: 16px)
// Set a value (add or update)
$updated: map.set($default-theme, 'primary', #ff6600);
// Result: (primary: #ff6600, secondary: #6c757d, font-size: 16px)
// Deep set nested value
$nested: map.set($default-theme, 'typography', 'h1', 2.5rem);
// Result: (primary: ..., secondary: ..., font-size: ..., typography: (h1: 2.5rem))
// Check map depth
$is-deep: map.depth($nested); // 2
Expected output: map.merge() combines two maps. map.deep-merge() merges deeply nested maps recursively. map.set() updates or adds entries. map.depth() checks nesting level.
Code Example: Iterating Maps
@use 'sass:map';
// Basic @each with keys and values
$theme-colors: (
'primary': #0066CC,
'secondary': #6c757d,
'success': #28a745,
'danger': #dc3545,
'warning': #ffc107,
'info': #17a2b8
);
@each $name, $color in $theme-colors {
.text-#{$name} { color: $color; }
.bg-#{$name} { background: $color; }
.border-#{$name} { border-color: $color; }
.btn-#{$name} {
background: $color;
color: #fff;
&:hover {
background: darken($color, 10%);
}
}
}
// Iterate with keys only
@each $name in map.keys($theme-colors) {
.badge-#{$name} {
background: map.get($theme-colors, $name);
}
}
// Nested map iteration
$components: (
'card': (
'padding': 1.5rem,
'radius': 8px,
'shadow': 0 2px 8px rgba(0,0,0,0.1)
),
'button': (
'padding': 0.75rem 1.5rem,
'radius': 4px,
'font-size': 1rem
)
);
@each $component, $props in $components {
.#{$component} {
@each $prop, $value in $props {
@if $prop == 'padding' {
padding: $value;
} @else if $prop == 'radius' {
border-radius: $value;
} @else if $prop == 'shadow' {
box-shadow: $value;
} @else if $prop == 'font-size' {
font-size: $value;
}
}
}
}
Expected output: @each with maps iterates over key-value pairs. Utility classes (text-primary, bg-primary) are generated automatically. Nested maps enable multi-level component configuration.
Code Example: Advanced Map Patterns
@use 'sass:map';
// Design token map with nested structure
$tokens: (
'color': (
'brand': (
'primary': #0066CC,
'secondary': #6c757d,
'accent': #ff6600
),
'neutral': (
'white': #ffffff,
'gray-100': #f8f9fa,
'gray-200': #e9ecef,
'gray-800': #343a40,
'black': #000000
),
'semantic': (
'success': #28a745,
'error': #dc3545,
'warning': #ffc107,
'info': #17a2b8
)
),
'spacing': (
'xs': 4px,
'sm': 8px,
'md': 16px,
'lg': 24px,
'xl': 32px,
'xxl': 48px
),
'typography': (
'font-family': (
'sans': ('Inter', system-ui, sans-serif),
'mono': ('Fira Code', monospace)
),
'font-size': (
'xs': 0.75rem,
'sm': 0.875rem,
'base': 1rem,
'lg': 1.125rem,
'xl': 1.25rem,
'2xl': 1.5rem,
'3xl': 2rem
)
),
'breakpoint': (
'sm': 480px,
'md': 768px,
'lg': 1024px,
'xl': 1280px
),
'z-index': (
'dropdown': 100,
'sticky': 200,
'nav': 300,
'overlay': 400,
'modal': 500
)
);
// Deep token access function
@function token($keys...) {
$current: $tokens;
@each $key in $keys {
@if map.has-key($current, $key) {
$current: map.get($current, $key);
} @else {
@error "Token not found: #{$keys}";
}
}
@return $current;
}
// Usage
.btn-primary {
background: token('color', 'brand', 'primary'); // #0066CC
padding: token('spacing', 'sm') token('spacing', 'md'); // 8px 16px
font-family: token('typography', 'font-family', 'sans');
font-size: token('typography', 'font-size', 'base');
z-index: token('z-index', 'dropdown'); // 100
}
@media (min-width: token('breakpoint', 'md')) {
.container {
max-width: 720px;
}
}
// Theming with map deep-merge
$dark-tokens: map.deep-merge($tokens, (
'color': (
'brand': (
'primary': #4da6ff
),
'neutral': (
'white': #1a1a2e,
'gray-100': #2d2d44,
'black': #ffffff
)
)
));
[data-theme="dark"] {
background: token('color', 'neutral', 'white');
color: token('color', 'neutral', 'black');
}
Expected output: The token() function provides dot-notation-like access to nested maps. Deep merge enables theme overrides that only change specific tokens. A single $tokens map drives all design decisions.
Common Mistakes
- Using map functions without @use 'sass:map' — Map functions require the sass:map module. Without it, they cause compilation errors.
- Accessing missing keys — map.get() returns null for missing keys. Use map.has-key() to check first, or use @error for clear messages.
- Shallow merge when deep merge is needed — map.merge() overwrites entire nested values. Use map.deep-merge() for recursive merging.
- Hard-coded map keys in multiple places — Access map values with lookup functions. Hard-coded keys scatter the configuration.
- Not using quoted string keys — Keys can be unquoted strings or quoted. Consistency matters. Quoted strings are more predictable.
- Too much nesting — Maps nested 5+ levels deep are hard to read and maintain. Keep to 2-3 levels.
- Mutating shared maps — Functions like map.set() return new maps. If you modify a global map, other modules see the original.
Practice Questions
- How do you access a value in a Sass map? map.get($map, $key) returns the value for the key.
- What is the difference between map.merge() and map.deep-merge()? merge() shallowly combines maps. deep-merge() recursively merges nested maps.
- How do you iterate over a map's keys and values? @each $key, $value in $map { ... }
- What does map.has-key() return? Returns true if the map contains the key, false otherwise.
FAQ
Mini Project
Build a complete design token system using nested Sass maps. Create a $tokens map with: color (brand, neutral, semantic), spacing (xs through xxl), typography (font-family, font-size, line-height), breakpoint (sm through xl), and z-index. Create a token() function for deep access. Create a dark theme variant using map.deep-merge(). Use @each to generate utility classes (text-, bg-, font-, p-, m-*) from the tokens. Build a sample page (header, buttons, cards, grid layout, alerts) that uses only token values. Demonstrate that changing one token value updates the entire page.
What's Next
Continue with Lesson 14: Sass and CSS Output to learn controlling CSS output from Sass.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro