用 SCSS 变量+map+@function 构建语义化间距系统,可统一维护、支持计算与响应式;仅用 margin/padding 工具类会导致语义断裂、响应式乏力、无法参与运算。

直接说结论:用 SCSS 变量 + map + @function 构建间距系统,比硬写 margin-top: 16px 强十倍;但若只靠 @mixin spacing($size) 这种简单封装,反而会让团队更难统一和维护。
为什么不能只用 margin/padding 工具类?
常见错误是写一堆类似 .mt-8、.pb-16 的 utility class,再配个 SCSS 循环生成。问题在于:
- 语义断裂:没人记得
mt-12对应设计稿里的「小段落间距」还是「卡片内边距」 - 响应式乏力:
mt-12在移动端可能太大,但加媒体查询后变成mt-12@sm,命名爆炸 - 无法参与计算:你想写
padding: $space-md * 1.5?不行,因为$space-md是字符串或未定义变量
用 SCSS map 定义语义化间距基准
核心是把「尺寸」和「用途」解耦——先定义一套基础数值,再映射到语义名。例如:
$space-scale: ( 'xs': 4px, 'sm': 8px, 'md': 16px, 'lg': 24px, 'xl': 32px, '2xl': 48px ); <p>$space: ( 'inline': map-get($space-scale, 'sm'), 'block': map-get($space-scale, 'md'), 'section': map-get($space-scale, 'xl'), 'gutter': map-get($space-scale, 'lg') );
这样 margin-bottom: map-get($space, 'block') 就有明确上下文,且所有值都是真实数值,可参与运算、缩放、响应式插值。
立即学习“前端免费学习笔记(深入)”;
关键点:
- 不要把
$space直接暴露给组件使用,而是封装成函数或 mixin -
map-get($space-scale, 'sm')比$space-sm更易扩展(比如后期加'xxs': 2px不影响现有 key) - 设计系统里「gutter」和「section」必须分开,因为栅格间距和内容区块间距的修改频率与意图完全不同
用 @function 实现带语义的间距计算
手动写 margin: map-get($space, 'block') 0 map-get($space, 'section') 0 太啰嗦。写一个函数:
@function space($key, $multiplier: 1) {
@if not map-has-key($space, $key) {
@warn "Unknown space key '#{$key}'";
@return 0;
}
@return map-get($space, $key) * $multiplier;
}然后就能自然地写:
.card {
padding: space('block') space('inline') space('block') * 1.5;
margin-bottom: space('section');
}
<p>@media (max-width: 768px) {
.card {
margin-bottom: space('section', 0.75);
}
}注意:
-
$multiplier必须是数字,不能是字符串(如'1.5'),否则乘法失效 - 函数里加
@warn能在编译时报错提示,比运行时样式错位更容易定位 - 别在函数里做单位转换(比如 px → rem),那会污染语义;单位应在最外层决定(如全局用
px,或统一转rem)
排版网格必须和间距系统联动
字体行高、段落间距、标题与正文距离,这些不是独立参数。比如你设了 $line-height-base: 1.5,那么 paragraph 的 margin-bottom 就该是 space('block') * $line-height-base,而不是另起一套数值。
实际做法:
- 定义
$type-rhythm: space('block')作为排版节奏基准(通常等于line-height × font-size) - 所有段落、列表、标题的垂直间距都基于它派生:
margin-bottom: $type-rhythm * 1.2 - Grid 的
gap也复用同一套$spacemap:gap: space('gutter'),确保栅格间隙与内容节奏一致
最容易被忽略的一点:当设计师说「标题下面空一行」,这一行必须是 line-height × font-size,而不是固定 24px —— 否则换字体或字号时整个节奏就垮了。所以排版网格的「行」本质是相对单位,而 SCSS 的 space() 函数必须能承载这种相对性。


















