Scss 的四种导入方式你都知道吗

226 阅读2分钟

想把样式拆模块、做主题、又不想全局变量乱飞?这篇把 SCSS 的四种“导入/组织”方式一次讲透:@use@forward、Sass 旧式 @import、以及 CSS 的 @import url(...)。含示例、对比表、迁移步骤与避坑清单。


@import "xxx":Sass 旧式导入(已弃用

作用
编译期把被导入的 SCSS 内容“直接拼接”到当前位置,变量/混入进入全局,容易重复加载、顺序踩坑。Dart Sass 已弃用,推荐使用@use/@forward

示例

@import "./tokens";   // 编译时把 tokens.scss 的内容贴进来(非 CSS 运行时)

@import url(...)CSS 的导入

作用
浏览器在运行时请求外部 CSS 文件;不会引入 Sass 的变量/混入/函数。

示例

@import url("/base.css");           /* 或者 @import "/print.css" print */

位置限制
必须在样式表最前面(在任何普通规则前;前面最多有 @charset / 其它 @import)。影响性能,一般不建议使用。


@use:模块化导入(推荐

作用
将另一个 SCSS 文件当作“模块”加载,默认通过命名空间访问变量/函数/混入;只加载一次、不污染全局,避免命名冲突。

示例

/* tokens/_color.scss */
$primary: #0b81ff !default;
@mixin btn { padding: 8px 12px; border-radius: 8px; }

/* app.scss */
@use "./tokens/color" as c; // 起别名 c

.button {
  color: c.$primary;
  @include c.btn();
}

配置默认变量(with + !default)

@use "./tokens/color" as c with (
  $primary: #0052d9   // 仅能配置标了 !default 的顶层公开变量
);

要点

  • 命名空间:@use "x" as x;不建议as *(去掉前缀,易冲突)。
  • 变量只读:c.$primary 不能在引入方直接赋值,只能用 with加载时配置。

@forward:聚合/转发导出

作用
把若干模块“转发”出去,做一个统一出口(barrel/index)。自己文件里不能直接使用转发来的成员;若要自用,再 @use 一次。

示例

/* design/_index.scss —— 聚合出口 */
@forward "../tokens/color" show $primary, btn;  // 只暴露想给外部用的成员
@forward "../tokens/spacing" as space-*;        // 导出时加前缀

/* app.scss —— 使用统一出口 */
@use "./design/index" as d;

.card {
  color: d.$primary;
  margin: d.$space-lg;
}

在出口处预配置主题(with)

/* design/_index.scss */
@forward "../tokens/color" with ($primary: #333);

注意:一个模块只能被配置一次。上游已通过 @forward ... with 配过,下游再配会报错。


五分钟速查表

能力/特性@use@forwardSass @import "x"CSS @import url(...)
发生时机编译期编译期编译期运行时(浏览器请求)
命名空间有(可 as * 去掉)对外导出,不给本文件用无(全局拼接)
去重加载❌ 可能重复N/A(浏览器请求)
变量可配置通过 with 配置 !default通过 with 预配置并转发通过“先定义后导入”覆盖(老做法)
全局污染
位置限制任意任意任意(编译期)顶部(在普通规则前)
适用场景模块化使用统一出口/SDK旧项目遗留引入纯 CSS(不推荐)

常见误区 & 快速排坑

  1. @import url('./variable.scss') 用后 $color 未定义

    • 这是 CSS 导入,不会带来 Sass 变量。
    • 用:@use "./variable" as v;color: v.$color;
  2. 我在文件里写 $primary: red,为啥 @use 来的变量没变?

    • @use 是模块隔离;你改的是当前文件$primary,不是模块里的。
    • 正确:@use "./tokens" with ($primary: red); 且源变量需 !default
  3. 去命名空间 as *@import 一样吗?

    • 不是。as * 只是省掉前缀,仍是模块系统(只加载一次、不污染全局)。
    • 有冲突风险:多个模块导出同名变量会报错。
  4. @forward 文件里用不了转发来的变量?

    • 对。@forward 只是出口;若当前文件要用,@use 一次
  5. 位置问题:为啥我的 @import 被忽略?

    • CSS 的 @import 必须在最顶部(普通规则之前)。Sass 旧式 @import 不限位置,但已经弃用。

迁移指北:从 @import@use/@forward

目录建议

styles/
  tokens/
    _color.scss     // 变量均加 !default
    _spacing.scss
  mixins/
    _typography.scss
  design/
    _index.scss     // 聚合出口(只 forward)
  app.scss          // 项目入口(只 use design)

改造步骤

  1. 给需要对外可配的变量都加 !default

  2. 建“总出口”:

    /* design/_index.scss */
    @forward "../tokens/color";
    @forward "../tokens/spacing";
    @forward "../mixins/typography";
    
  3. 入口使用:

    /* app.scss */
    @use "./design/index" as d with (
      $primary: #0052d9,
      $space-lg: 24px
    );
    
    .btn { color: d.$primary; margin: d.$space-lg; }
    
  4. 删除旧式 @import,逐步把业务文件改为 @use 指向 design/_index.scss


结语

  • 新项目:只用 @use + @forward
  • 做 SDK/设计系统:@forward 聚合成一个总入口,外部只 @use 它。
  • 变量可配:源头加 !default,引入处用 with
  • 避免 @import 与 CSS 的 @import url(...)(性能差、易踩坑)。

需要我按你的项目目录,直接给一份可跑的 @use/@forward 模板吗?把目录贴过来我就给你落地版。