SASS - 在多个文件中使用变量

345

我希望能够保留一个中心的.scss文件,用于存储项目中所有SASS变量定义。

// _master.scss 

$accent: #6D87A7;           
$error: #811702;
$warning: #F9E055;
$valid: #038144;
// etc... 

由于项目的性质,它将拥有大量的CSS文件。在一个位置声明所有项目范围内的样式变量非常重要。

在SCSS中有没有这样的方法?


我非常确定这是不可能的,我之前尝试过同样的事情,但无法使其工作。 - DrCord
12
相反,这是SASS的一个核心特性:http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#partials - Ennui
太好了!我想我可能误读了这个语句:“只允许在文档的基本级别上使用的指令,例如mixin或charset,在嵌套上下文中导入的文件中是不允许的。”并没有正确阅读“嵌套上下文”部分。 - DrCord
8个回答

446

你可以这样做:

我有一个名为“utilities”的文件夹,里面有一个名为“_variables.scss”的文件。

在那个文件中,我像这样声明变量:

$black: #000;
$white: #fff;

然后我有一个style.scss文件,在该文件中我像这样导入所有其他的scss文件:

// Utilities
@import "utilities/variables";

// Base Rules
@import "base/normalize";
@import "base/global";

接下来,在我导入的任何文件中,我都应该能够访问我声明的变量。

只需确保在您希望在其中使用它的任何其他文件之前导入变量文件即可。


8
完美。正是我所想要和需要的。最后一个问题:所有导入的文件都应该以下划线开头吗?你在文件名中使用了下划线,但在@import声明中却没有。 - dthree
62
这些文件被认为是部分文件,它们的名称必须以下划线开头,但在导入时可以省略下划线。这里有一篇非常好的文章详细介绍了原因:http://alistapart.com/article/getting-started-with-sass - Joel
7
请注意,你可以在你的模块内声明默认值$black: #000 !default;!default这个东西可以防止变量被重置,如果它已经存在的话。 - Andrey Mikhaylov - lolmaus
2
为什么我们必须把所有变量都倒入一个单独的文件中?难道我们不能将它们分割并放置在需要它们的相应文件中吗?例如,用于模态对话框的变量,我们不能将它们放置在_modal.scss中吗? - VJAI
11
这个答案不再是在多个文件中重复使用变量的推荐方法。请参考 https://dev59.com/jGMm5IYBdhLWcg3wdeya#61500282。 - whiscode
显示剩余4条评论

220

这个问题很久以前就被问过了,所以我想发布一个更新的答案。

现在应该避免使用@import。从文档中可以看到:

Sass将逐步淘汰它,并在未来几年内将其完全从语言中移除。最好使用@use规则。

这里可以找到所有原因的完整列表

你现在应该使用如下的@use

_variables.scss

$text-colour: #262626;

_otherFile.scss

@use 'variables'; // Path to _variables.scss Notice how we don't include the underscore or file extension

body {
  // namespace.$variable-name
  // namespace is just the last component of its URL without a file extension
  color: variables.$text-colour;
}

你还可以为命名空间创建别名: _otherFile.scss
@use 'variables' as v;

body {
  // alias.$variable-name
  color: v.$text-colour;
}

编辑 此文撰写时(2020年11月),如@und3rdg所指出的,@use 仅适用于Dart Sass,而不支持 LibSass(现已弃用)或Ruby Sass。请参阅https://sass-lang.com/documentation/at-rules/use 以获取最新兼容性信息。


16
这应该是现在的所选答案,因为"import"被标记为已弃用并将在未来被删除。 - Timtim
1
这只适用于dart-sass,它的性能比libsass差得多。 - undg
@whiscode 是的,你说得对 :,( LibSass已经死了,DartSass万岁!- https://sass-lang.com/blog/libsass-is-deprecated - undg
"Dart Sass比Ruby Sass快5-10倍,仅比LibSass慢1.5倍" - 来源 ==> 该答案在2021年应被接受。 - s3c
2
对于全局变量,我倾向于使用@use 'variables' as *,因为它不需要为每个变量使用前缀。 - theking2
显示剩余2条评论

101

这个答案展示了我最终使用它的方式以及我遇到的额外陷阱。

我创建了一个主SCSS文件,这个文件必须以下划线开头才能被导入:

// assets/_master.scss 
$accent: #6D87A7;           
$error: #811702;

然后,在我所有其他的 .SCSS 文件的头部,我导入主文件:

// When importing the master, you leave out the underscore, and it
// will look for a file with the underscore. This prevents the SCSS
// compiler from generating a CSS file from it.
@import "assets/master";

// Then do the rest of my CSS afterwards:
.text { color: $accent; }

重要提示

在您的_master.scss文件中,请仅包含变量、函数声明和其他SASS功能。如果您包含了实际的CSS,它将会在您将主文件导入到每个文件中时在每个文件中复制此CSS。


6
非常感谢您对文件需要以下划线开头的评论!我刚刚花了大约3个小时试图弄清楚为什么我缺少了一堆Foundation样式。将我的Foundation设置文件名更改为以下划线开头,嘿哎呀!但是现在当我再次将文件名更改回来时,它仍然可以工作?这是怎么回事?唉...叹气并接受它现在正在工作 - poshaughnessy
5
别改回去了——它可能是在工作时使用了从你的 SCSS 文件生成的 CSS。只需使用下划线即可。但除此之外,你做得很好,使其工作起来了! - dthree
@poshaughnessy 这可能有效,因为Sass使用缓存,所以它可以被缓存。不过我不能100%确定。 - PeterM
根据您的编译器,它可能正在使用“上次已知的良好配置”方法。我知道 MVC Core 项目不会编译破损的文件,您将仍然拥有旧文件。 - Ben Sampica
2
你是正确的,@rinogo。 - dthree
显示剩余2条评论

5
在 Angular v10 中,我做了这样一件事情,首先创建了一个名为 master.scss 的文件,并包含以下变量: master.scss 文件:

$theme: blue;

$button_color: red;

$label_color: gray;

接着我在 style.scss 文件的顶部引入了 master.scss 文件:

style.scss 文件内容如下:

@use './master' as m;

请确保在顶部导入master.scssm是命名空间的别名;
根据下面的官方文档,使用@use而不是@importhttps://sass-lang.com/documentation/at-rules/import 然后,在您的styles.scss文件中,您可以使用任何在master.scss中定义的变量,如下所示:
someClass {

   backgroud-color: m.$theme;

   color: m.$button_color;

}

希望这能帮到你...

愉快的编程 :)


4
创建一个index.scss文件,你可以在里面导入所有的文件结构。我会给你粘贴一个来自企业项目的index文件,或许它能帮助其他人如何在css中组织文件:
@import 'base/_reset';

@import 'helpers/_variables';
@import 'helpers/_mixins';
@import 'helpers/_functions';
@import 'helpers/_helpers';
@import 'helpers/_placeholders';

@import 'base/_typography';

@import 'pages/_versions';
@import 'pages/_recording';
@import 'pages/_lists';
@import 'pages/_global';

@import 'forms/_buttons';
@import 'forms/_inputs';
@import 'forms/_validators';
@import 'forms/_fieldsets';

@import 'sections/_header';
@import 'sections/_navigation';
@import 'sections/_sidebar-a';
@import 'sections/_sidebar-b';
@import 'sections/_footer';

@import 'vendors/_ui-grid';

@import 'components/_modals';
@import 'components/_tooltip';
@import 'components/_tables';
@import 'components/_datepickers';

您可以使用gulp/grunt/webpack等工具来观看它们,例如:

gulpfile.js

// SASS任务

var gulp = require('gulp');
var sass = require('gulp-sass');
//var concat = require('gulp-concat');
var uglifycss = require('gulp-uglifycss');
var sourcemaps = require('gulp-sourcemaps');

gulp.task('styles', function(){
    return gulp
            .src('sass/**/*.scss')
            .pipe(sourcemaps.init())
            .pipe(sass().on('error', sass.logError))
            .pipe(concat('styles.css'))
            .pipe(uglifycss({
                "maxLineLen": 80,
                "uglyComments": true
            }))
            .pipe(sourcemaps.write('.'))
            .pipe(gulp.dest('./build/css/'));
});

gulp.task('watch', function () {
    gulp.watch('sass/**/*.scss', ['styles']);
});

gulp.task('default', ['watch']);

1
你难道不应该从@import语句中省略下划线吗? - Quantum7
2
Sass的'@import'两种写法都可以。你可以带下划线或不带下划线写URI,也可以带或不带'.scss'后缀。 - Pony

4

正如先前提到的那样,在较新版本的SASS中不推荐使用@import。相反,在文件顶部使用@use "SASS局部文件路径"代替。

你需要将 SASS 局部文件导入(使用@use)到每个使用它的 SASS 文件中,而不仅仅是你的主文件。

假设我们有一个名为_variables.scss*的SASS文件在名为partials的文件夹中,我们想在header.scss中使用它。因此在header.scss中编写以下内容:

@use "partials/variables" as *

现在你可以使用所有在_variables.scss*中定义的变量,只需使用$variable(无前缀)。或者,您可以使用命名空间(就像Christian已经提到的那样)

@use "partials/variables" as v

使用v.$variable来引用_variables.scss*里面的变量。

*注意,SASS编译器会忽略下划线,这样就不会为每个SASS局部文件生成单独的CSS文件。相反,您只需使用@use将它们全部导入到主SASS文件中即可。


1
我找到了一个使用vite解决vue3问题的方法。如果你正在使用dart-sass,你可以通过使用@forward@use来避免sass模块的全局限制。 _master.scss
$accent: #6D87A7;           
$error: #811702;
$warning: #F9E055;
$valid: #038144;
// etc... 

_global.scss

@forward '_master.scss';
// etc...

然后在 vite.config.js 中配置您的 CSS 选项,如下所示:
export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `
          @use "./<path-to-file>/_globals.scss" as *;
        `,
      },
    },
  },
// etc...
});

如sass文档中提到,当导入没有命名空间的模块时

我们建议您仅在自己编写的样式表中这样做;否则,它们可能会引入新成员导致名称冲突!

然后您可以在任何其他样式表或组件中使用其他@use模块,如下所示

// component file needing a function module

@use 'functions.scss';

1
对于使用 Vite 的人来说,这是一个很好的答案。 - Isaac Weingarten

1

我们可以在全局的sass文件中编写一些基于颜色的类,这样我们就不需要关心变量在哪里了。就像下面这样:

// base.scss 
@import "./_variables.scss";

.background-color{
    background: $bg-color;
}

然后,我们可以在任何文件中使用background-color类。 我的意思是,我不需要在任何文件中导入variable.scss,只需使用它即可。


1
显而易见的想法并不好,你可以有很多变量,并且只使用导入来保持索引更加清晰,每个文件都有自己的目的。 - Carnaru Valentin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接