Sass 映射(Maps) #
什么是映射? #
映射(Maps)是 Sass 中的键值对数据结构,类似于其他语言中的对象(Object)或字典(Dictionary)。它是组织复杂数据的强大工具。
scss
$colors: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c
);
基本语法 #
定义映射 #
scss
// 基本映射
$map: (
key1: value1,
key2: value2,
key3: value3
);
// 空映射
$empty: ();
// 单行映射
$simple: (a: 1, b: 2, c: 3);
// 多行映射(推荐)
$config: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c,
warning: #f39c12
);
键和值 #
scss
// 键可以是任何类型
$map: (
"string-key": value1,
100: value2,
true: value3
);
// 值可以是任何类型
$complex: (
string: "hello",
number: 100px,
color: red,
list: 1px 2px 3px,
map: (nested: value),
boolean: true,
null: null
);
映射函数 #
map-get() - 获取值 #
scss
$colors: (
primary: #3498db,
secondary: #2ecc71
);
.element {
color: map-get($colors, primary); // #3498db
}
// 键不存在返回 null
$missing: map-get($colors, tertiary); // null
map-merge() - 合并映射 #
scss
$colors1: (
primary: #3498db,
secondary: #2ecc71
);
$colors2: (
danger: #e74c3c,
warning: #f39c12
);
$all-colors: map-merge($colors1, $colors2);
// (primary: #3498db, secondary: #2ecc71, danger: #e74c3c, warning: #f39c12)
// 覆盖值
$override: map-merge($colors1, (primary: #2980b9));
// (primary: #2980b9, secondary: #2ecc71)
map-keys() - 获取所有键 #
scss
$colors: (
primary: #3498db,
secondary: #2ecc71
);
$keys: map-keys($colors); // ("primary", "secondary")
// 遍历键
@each $key in map-keys($colors) {
.text-#{$key} {
color: map-get($colors, $key);
}
}
map-values() - 获取所有值 #
scss
$colors: (
primary: #3498db,
secondary: #2ecc71
);
$values: map-values($colors); // (#3498db, #2ecc71)
map-has-key() - 检查键是否存在 #
scss
$colors: (
primary: #3498db
);
$exists: map-has-key($colors, primary); // true
$missing: map-has-key($colors, secondary); // false
// 实际应用
@function get-color($name) {
@if not map-has-key($colors, $name) {
@error "Color '#{$name}' not found";
}
@return map-get($colors, $name);
}
map-remove() - 移除键 #
scss
$colors: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c
);
$reduced: map-remove($colors, danger);
// (primary: #3498db, secondary: #2ecc71)
// 移除多个键
$minimal: map-remove($colors, secondary, danger);
// (primary: #3498db)
map.set() - 设置值(Dart Sass) #
scss
@use "sass:map";
$colors: (
primary: #3498db
);
$updated: map.set($colors, secondary, #2ecc71);
// (primary: #3498db, secondary: #2ecc71)
map.deep-merge() - 深度合并(Dart Sass) #
scss
@use "sass:map";
$base: (
colors: (
primary: #3498db
)
);
$override: (
colors: (
secondary: #2ecc71
)
);
$merged: map.deep-merge($base, $override);
// (colors: (primary: #3498db, secondary: #2ecc71))
嵌套映射 #
定义嵌套映射 #
scss
$theme: (
colors: (
primary: (
base: #3498db,
light: #5dade2,
dark: #2980b9
),
secondary: (
base: #2ecc71,
light: #58d68d,
dark: #27ae60
)
),
spacing: (
sm: 8px,
md: 16px,
lg: 24px
)
);
深度获取函数 #
scss
@function map-deep-get($map, $keys...) {
@each $key in $keys {
$map: map-get($map, $key);
}
@return $map;
}
.element {
color: map-deep-get($theme, colors, primary, base); // #3498db
padding: map-deep-get($theme, spacing, md); // 16px
}
深度设置函数 #
scss
@function map-deep-set($map, $keys..., $value) {
$length: length($keys);
$key: nth($keys, $length);
@if $length > 1 {
$parent-keys: slice($keys, 1, $length - 1);
$parent: map-deep-get($map, $parent-keys...);
$parent: map-merge($parent, ($key: $value));
@return map-deep-set($map, $parent-keys..., $parent);
}
@return map-merge($map, ($key: $value));
}
实际应用示例 #
设计令牌系统 #
scss
$design-tokens: (
colors: (
brand: (
primary: #3498db,
secondary: #2ecc71
),
semantic: (
success: #2ecc71,
warning: #f39c12,
danger: #e74c3c,
info: #3498db
),
neutral: (
white: #ffffff,
light: #f5f5f5,
base: #333333,
dark: #1a1a1a,
black: #000000
)
),
typography: (
font-family: (
base: ('Helvetica Neue', Arial, sans-serif),
heading: ('Georgia', serif)
),
font-size: (
xs: 0.75rem,
sm: 0.875rem,
base: 1rem,
lg: 1.125rem,
xl: 1.25rem,
2xl: 1.5rem,
3xl: 1.875rem,
4xl: 2.25rem
),
font-weight: (
light: 300,
normal: 400,
medium: 500,
semibold: 600,
bold: 700
),
line-height: (
tight: 1.25,
base: 1.5,
relaxed: 1.75
)
),
spacing: (
0: 0,
1: 0.25rem,
2: 0.5rem,
3: 1rem,
4: 1.5rem,
5: 3rem
),
breakpoints: (
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 1400px
),
shadows: (
sm: 0 1px 2px rgba(0, 0, 0, 0.05),
base: 0 1px 3px rgba(0, 0, 0, 0.1),
md: 0 4px 6px rgba(0, 0, 0, 0.1),
lg: 0 10px 15px rgba(0, 0, 0, 0.1),
xl: 0 20px 25px rgba(0, 0, 0, 0.1)
),
radius: (
none: 0,
sm: 0.125rem,
base: 0.25rem,
md: 0.375rem,
lg: 0.5rem,
xl: 0.75rem,
full: 9999px
)
);
// 访问函数
@function token($keys...) {
@return map-deep-get($design-tokens, $keys...);
}
// 使用
.element {
color: token(colors, brand, primary);
font-size: token(typography, font-size, lg);
padding: token(spacing, 3);
border-radius: token(radius, md);
box-shadow: token(shadows, base);
}
主题系统 #
scss
$themes: (
light: (
background: #ffffff,
text: #333333,
primary: #3498db,
secondary: #2ecc71,
border: #e0e0e0,
shadow: rgba(0, 0, 0, 0.1)
),
dark: (
background: #1a1a1a,
text: #ffffff,
primary: #5dade2,
secondary: #58d68d,
border: #333333,
shadow: rgba(0, 0, 0, 0.3)
)
);
@mixin theme($name) {
$theme: map-get($themes, $name);
background-color: map-get($theme, background);
color: map-get($theme, text);
.button {
background-color: map-get($theme, primary);
color: map-get($theme, background);
}
.card {
background-color: map-get($theme, background);
border-color: map-get($theme, border);
box-shadow: 0 2px 4px map-get($theme, shadow);
}
}
.theme-light {
@include theme(light);
}
.theme-dark {
@include theme(dark);
}
响应式断点 #
scss
$breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 1400px
);
@mixin media-up($breakpoint) {
$value: map-get($breakpoints, $breakpoint);
@if $value != null {
@media (min-width: $value) {
@content;
}
} @else {
@error "Breakpoint '#{$breakpoint}' not found";
}
}
@mixin media-down($breakpoint) {
$value: map-get($breakpoints, $breakpoint);
@if $value != null {
@media (max-width: $value - 1px) {
@content;
}
}
}
@mixin media-between($lower, $upper) {
$lower-value: map-get($breakpoints, $lower);
$upper-value: map-get($breakpoints, $upper);
@media (min-width: $lower-value) and (max-width: $upper-value - 1px) {
@content;
}
}
// 使用
.container {
padding: 15px;
@include media-up(md) {
padding: 30px;
}
@include media-between(md, lg) {
max-width: 720px;
}
}
Z-index 管理 #
scss
$z-indexes: (
modal: 1000,
overlay: 900,
dropdown: 800,
sticky: 700,
fixed: 600,
header: 500,
footer: 400,
default: 1,
below: -1
);
@function z($layer) {
@if map-has-key($z-indexes, $layer) {
@return map-get($z-indexes, $layer);
}
@warn "Unknown z-index layer: #{$layer}";
@return 1;
}
.modal {
z-index: z(modal);
}
.overlay {
z-index: z(overlay);
}
.dropdown {
z-index: z(dropdown);
}
间距系统 #
scss
$spacing: (
base: 8px,
scale: (
0: 0,
1: 0.25,
2: 0.5,
3: 1,
4: 1.5,
5: 2,
6: 3,
7: 4,
8: 6
)
);
@function spacing($level: 3) {
$multiplier: map-deep-get($spacing, scale, $level);
@return map-get($spacing, base) * $multiplier * 4;
}
.section {
padding: spacing(4);
margin-bottom: spacing(3);
}
.grid {
gap: spacing(2);
}
组件配置 #
scss
$button-config: (
sizes: (
sm: (
padding: 0.25rem 0.5rem,
font-size: 0.875rem
),
md: (
padding: 0.5rem 1rem,
font-size: 1rem
),
lg: (
padding: 0.75rem 1.5rem,
font-size: 1.125rem
)
),
variants: (
primary: (
background: #3498db,
color: white,
border: transparent
),
secondary: (
background: #95a5a6,
color: white,
border: transparent
),
outline: (
background: transparent,
color: #3498db,
border: #3498db
)
),
radius: (
none: 0,
sm: 0.25rem,
md: 0.5rem,
full: 9999px
)
);
@mixin button-size($size) {
$config: map-deep-get($button-config, sizes, $size);
padding: map-get($config, padding);
font-size: map-get($config, font-size);
}
@mixin button-variant($variant) {
$config: map-deep-get($button-config, variants, $variant);
background-color: map-get($config, background);
color: map-get($config, color);
border-color: map-get($config, border);
}
.btn {
@include button-size(md);
@include button-variant(primary);
border-radius: map-deep-get($button-config, radius, md);
}
.btn-sm {
@include button-size(sm);
}
.btn-lg {
@include button-size(lg);
}
.btn-secondary {
@include button-variant(secondary);
}
.btn-outline {
@include button-variant(outline);
}
映射工具函数 #
深度合并 #
scss
@function map-deep-merge($map1, $map2) {
$result: $map1;
@each $key, $value in $map2 {
@if type-of($value) == map and type-of(map-get($result, $key)) == map {
$result: map-merge($result, ($key: map-deep-merge(map-get($result, $key), $value)));
} @else {
$result: map-merge($result, ($key: $value));
}
}
@return $result;
}
映射遍历 #
scss
@function map-to-list($map) {
$list: ();
@each $key, $value in $map {
$list: append($list, ($key $value));
}
@return $list;
}
键值反转 #
scss
@function map-invert($map) {
$result: ();
@each $key, $value in $map {
$result: map-merge($result, ($value: $key));
}
@return $result;
}
最佳实践 #
1. 使用嵌套映射组织复杂数据 #
scss
// 好:结构清晰
$theme: (
colors: (
primary: #3498db
),
spacing: (
base: 8px
)
);
// 不好:扁平结构
$color-primary: #3498db;
$spacing-base: 8px;
2. 提供默认值 #
scss
@function get($map, $key, $default: null) {
@if map-has-key($map, $key) {
@return map-get($map, $key);
}
@return $default;
}
3. 错误处理 #
scss
@function get-required($map, $key) {
@if not map-has-key($map, $key) {
@error "Key '#{$key}' not found in map";
}
@return map-get($map, $key);
}
下一步 #
掌握了映射(Maps)后,继续学习 继承扩展,了解 @extend 指令的使用!
最后更新:2026-03-28