Maps: Creating & Advanced Operations
Introduction to SASS Maps
SASS maps are one of the most powerful data structures in SASS. They allow you to store key-value pairs, similar to objects in JavaScript or dictionaries in Python. Maps are incredibly useful for organizing related data and creating scalable systems for colors, breakpoints, spacing, and more.
What Are SASS Maps?
A map is a collection of key-value pairs enclosed in parentheses. Each key must be unique and is separated from its value by a colon. Multiple pairs are separated by commas:
Basic Map Syntax
$colors: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c,
warning: #f39c12,
info: #16a085
);
$breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
);
$map-name: (key1: value1, key2: value2). You can use any data type as values, including strings, numbers, colors, lists, and even other maps.
Why Use Maps?
Maps provide several advantages over traditional variables:
- Organization: Group related values together logically
- Scalability: Easy to add, remove, or modify values
- Iteration: Loop through map entries with @each
- Maintainability: Single source of truth for related data
- Flexibility: Create complex data structures with nested maps
Accessing Map Values
Using map-get() Function
The map-get() function retrieves a value from a map by its key:
Accessing Map Values
$colors: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c
);
.button {
background-color: map-get($colors, primary); // #3498db
&:hover {
background-color: darken(map-get($colors, primary), 10%);
}
}
.alert-danger {
color: map-get($colors, danger); // #e74c3c
border-color: map-get($colors, danger);
}
Modern map.get() Syntax
With the SASS module system, you can use map.get() from the map module:
Using map.get() with @use
@use "sass:map";
$colors: (
primary: #3498db,
secondary: #2ecc71
);
.card {
background: map.get($colors, primary);
border: 1px solid map.get($colors, secondary);
}
map.get() syntax is the modern, module-based approach. If you're using the @use rule, prefer map.get() over map-get().
Checking for Keys
map-has-key() Function
Before accessing a map value, you might want to check if a key exists:
Checking Key Existence
$theme: (
primary: #3498db,
secondary: #2ecc71
);
@if map-has-key($theme, primary) {
.btn-primary {
background: map-get($theme, primary);
}
}
@if not map-has-key($theme, tertiary) {
@warn "Tertiary color is not defined in theme";
}
Safe Access Pattern
Create a safe getter function that returns a fallback value:
Safe Map Access Function
@function get-color($key, $fallback: #000) {
$colors: (
primary: #3498db,
secondary: #2ecc71
);
@if map-has-key($colors, $key) {
@return map-get($colors, $key);
}
@warn "Color '#{$key}' not found. Using fallback.";
@return $fallback;
}
.element {
color: get-color(primary); // #3498db
background: get-color(tertiary, #ccc); // #ccc with warning
}
Getting Keys and Values
map-keys() Function
Extract all keys from a map as a list:
Extracting Map Keys
$spacing: (
xs: 0.25rem,
sm: 0.5rem,
md: 1rem,
lg: 1.5rem,
xl: 3rem
);
$spacing-keys: map-keys($spacing);
// Result: (xs, sm, md, lg, xl)
@debug $spacing-keys; // Output in console
map-values() Function
Extract all values from a map as a list:
Extracting Map Values
$font-sizes: (
small: 0.875rem,
normal: 1rem,
large: 1.25rem
);
$sizes: map-values($font-sizes);
// Result: (0.875rem, 1rem, 1.25rem)
// Find minimum font size
$min-size: min($sizes...);
Merging Maps
map-merge() Function
Combine two maps into a new map. If keys overlap, the second map's values take precedence:
Merging Maps
$default-colors: (
primary: #3498db,
secondary: #2ecc71,
text: #333
);
$custom-colors: (
primary: #e74c3c, // Override
accent: #9b59b6 // New key
);
$theme: map-merge($default-colors, $custom-colors);
// Result:
// (
// primary: #e74c3c, // Overridden
// secondary: #2ecc71,
// text: #333,
// accent: #9b59b6 // Added
// )
.app {
background: map-get($theme, primary); // #e74c3c
}
Merging Multiple Maps
Chain map-merge() calls to combine multiple maps:
Chaining Map Merges
$base: (
primary: blue
);
$theme-light: (
bg: white,
text: black
);
$theme-dark: (
bg: black,
text: white
);
$final-light: map-merge(map-merge($base, $theme-light), (
accent: yellow
));
// Result: (primary: blue, bg: white, text: black, accent: yellow)
Removing Keys
map-remove() Function
Create a new map with specified keys removed:
Removing Map Keys
$all-colors: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c,
warning: #f39c12,
deprecated-color: #ccc
);
$active-colors: map-remove($all-colors, deprecated-color);
// Result: Map without deprecated-color
// Remove multiple keys
$main-colors: map-remove($all-colors, warning, deprecated-color);
map-remove() and map-merge() do not modify the original map. They return a new map. Maps in SASS are immutable.
Nested Maps
Creating Nested Map Structures
Maps can contain other maps as values, allowing you to create complex data structures:
Nested Maps Example
$theme: (
colors: (
primary: #3498db,
secondary: #2ecc71,
shades: (
light: #5dade2,
dark: #2874a6
)
),
typography: (
font-family: "Inter, sans-serif",
sizes: (
small: 0.875rem,
normal: 1rem,
large: 1.25rem
)
),
spacing: (
xs: 0.25rem,
sm: 0.5rem,
md: 1rem
)
);
Accessing Nested Map Values
Access nested values by chaining map-get() calls:
Accessing Nested Values
$theme: (
colors: (
primary: #3498db,
shades: (
light: #5dade2,
dark: #2874a6
)
)
);
// Access nested value
$primary-light: map-get(map-get(map-get($theme, colors), shades), light);
// Create a helper function for easier access
@function theme-get($keys...) {
$value: $theme;
@each $key in $keys {
$value: map-get($value, $key);
}
@return $value;
}
.button {
background: theme-get(colors, primary); // #3498db
&:hover {
background: theme-get(colors, shades, dark); // #2874a6
}
}
Iterating Over Maps
Using @each with Maps
Loop through map entries to generate CSS dynamically:
Basic Map Iteration
$colors: (
primary: #3498db,
success: #2ecc71,
danger: #e74c3c,
warning: #f39c12
);
@each $name, $color in $colors {
.btn-#{$name} {
background-color: $color;
border-color: darken($color, 10%);
&:hover {
background-color: darken($color, 15%);
}
}
}
// Generated CSS:
// .btn-primary { background-color: #3498db; ... }
// .btn-success { background-color: #2ecc71; ... }
// .btn-danger { background-color: #e74c3c; ... }
// .btn-warning { background-color: #f39c12; ... }
Advanced Iteration Examples
Generating Utility Classes
$spacing-scale: (
0: 0,
1: 0.25rem,
2: 0.5rem,
3: 0.75rem,
4: 1rem,
5: 1.5rem,
6: 2rem
);
$sides: (
t: top,
r: right,
b: bottom,
l: left
);
// Generate margin utilities
@each $key, $value in $spacing-scale {
.m-#{$key} { margin: $value; }
.p-#{$key} { padding: $value; }
@each $side-key, $side-value in $sides {
.m#{$side-key}-#{$key} { margin-#{$side-value}: $value; }
.p#{$side-key}-#{$key} { padding-#{$side-value}: $value; }
}
}
// Generated: .m-0, .m-1, .mt-2, .pr-3, etc.
Real-World Use Cases
1. Theme Color System
Complete Theme System
$theme-colors: (
primary: (
base: #3498db,
light: #5dade2,
dark: #2874a6,
contrast: #fff
),
secondary: (
base: #2ecc71,
light: #58d68d,
dark: #229954,
contrast: #fff
),
neutral: (
base: #95a5a6,
light: #d5dbdb,
dark: #566573,
contrast: #fff
)
);
@function theme-color($color-name, $variant: base) {
@return map-get(map-get($theme-colors, $color-name), $variant);
}
.btn-primary {
background: theme-color(primary);
color: theme-color(primary, contrast);
&:hover {
background: theme-color(primary, dark);
}
}
2. Responsive Breakpoints
Breakpoint System
$breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 1400px
);
@function breakpoint($name) {
@if map-has-key($breakpoints, $name) {
@return map-get($breakpoints, $name);
}
@warn "Breakpoint '#{$name}' not found";
@return null;
}
@mixin respond-above($name) {
$breakpoint: breakpoint($name);
@if $breakpoint {
@media (min-width: $breakpoint) {
@content;
}
}
}
.container {
width: 100%;
@include respond-above(md) {
max-width: 720px;
}
@include respond-above(lg) {
max-width: 960px;
}
@include respond-above(xl) {
max-width: 1140px;
}
}
3. Z-Index Scale
Z-Index Management
$z-layers: (
base: 1,
dropdown: 100,
sticky: 200,
fixed: 300,
modal-backdrop: 400,
modal: 500,
popover: 600,
tooltip: 700,
toast: 800
);
@function z($layer) {
@if map-has-key($z-layers, $layer) {
@return map-get($z-layers, $layer);
}
@warn "Z-index layer '#{$layer}' not found";
@return 1;
}
.dropdown-menu {
z-index: z(dropdown);
}
.modal {
z-index: z(modal);
}
.tooltip {
z-index: z(tooltip);
}
4. Spacing System
Consistent Spacing
$spacing: (
none: 0,
xs: 0.25rem,
sm: 0.5rem,
md: 1rem,
lg: 1.5rem,
xl: 2rem,
xxl: 3rem,
xxxl: 4rem
);
@each $name, $value in $spacing {
.gap-#{$name} { gap: $value; }
.space-x-#{$name} > * + * { margin-left: $value; }
.space-y-#{$name} > * + * { margin-top: $value; }
}
// Custom spacing function
@function space($size) {
@return map-get($spacing, $size);
}
.card {
padding: space(md);
margin-bottom: space(lg);
}
Exercise 1: Color Palette System
Create a comprehensive color palette system using maps:
- Define a
$colorsmap with primary, secondary, success, danger, warning, and info colors - Each color should have a nested map with: base, light, lighter, dark, darker values
- Create a
color()function that accepts color name and variant - Generate button classes for each color using @each
- Each button should have hover states using the dark variant
Exercise 2: Responsive Typography
Build a responsive typography system:
- Create a
$font-sizesmap with heading levels (h1-h6) and body text - Each key should contain a nested map with sizes for mobile, tablet, and desktop
- Create a mixin that generates responsive font sizes using @media queries
- Apply the mixin to generate styles for all heading elements
- Add line-height and font-weight to the nested map structure
Exercise 3: Grid System with Maps
Create a flexible grid system using maps:
- Define a
$grid-columnsmap with column counts: 1, 2, 3, 4, 6, 12 - Create a
$grid-breakpointsmap (xs, sm, md, lg, xl) - Generate column classes: .col-1, .col-2, etc.
- Generate responsive classes: .col-md-6, .col-lg-4, etc.
- Add gap utilities using a
$grid-gapsmap
Summary
In this lesson, you learned:
- How to create and use SASS maps for organizing data
- Accessing map values with map-get() and map.get()
- Checking for keys with map-has-key()
- Extracting keys and values with map-keys() and map-values()
- Merging maps with map-merge() for configuration systems
- Removing keys with map-remove()
- Creating and accessing nested maps for complex data
- Iterating over maps with @each to generate CSS
- Real-world applications: theme systems, breakpoints, z-index scales, spacing
Maps are essential for building scalable, maintainable SASS architectures. They enable you to create sophisticated design systems, manage complex configurations, and generate repetitive CSS patterns efficiently. Master maps and you'll unlock the full power of SASS for large-scale projects.