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