SASS - use variables across multiple files
Asked Answered
R

9

351

I would like to keep one central .scss file that stores all SASS variable definitions for a project.

// _master.scss 

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

The project will have a large number of CSS files, due to its nature. It is important that I declare all project-wide style variables in one location.

Is there a way to do this in SCSS?

Rashidarashidi answered 11/7, 2013 at 16:43 Comment(3)
I am pretty sure that is not possible, I tried the same thing awhile ago and could not get it to work.Redhead
@Redhead on the contrary it is a central feature of SASS: sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#partialsIrish
Sweet! I think I may have misread this statement: "Directives that are only allowed at the base level of a document, like mixin or charset, are not allowed in files that are imported in a nested context." and not properly read the "nested context" part.Redhead
G
237

This question was asked a long time ago so I thought I'd post an updated answer.

You should now avoid using @import. Taken from the docs:

Sass will gradually phase it out over the next few years, and eventually remove it from the language entirely. Prefer the @use rule instead.

A full list of reasons can be found here

You should now use @use as shown below:

_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;
}

You can also create an alias for the namespace:

_otherFile.scss

@use 'variables' as v;

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

EDIT As pointed out by @und3rdg at the time of writing (November 2020) @use is currently only available for Dart Sass and not LibSass (now deprecated) or Ruby Sass. See https://sass-lang.com/documentation/at-rules/use for the latest compatibility

Glick answered 29/4, 2020 at 11:2 Comment(8)
This should be now the selected answer, since "import" is marked as deprecated and will be removed in the future.Brittan
This is true only for dart-sass that is way less performant than libsass.Variance
@und3rdg I've updated the post to reflect this compatibility point. It's worth mentioning that libsass is now deprecated There is a comment on the github page advising people to use Dart Sass instead for future projects - github.com/sass/libsassGlick
It's an interesting change which actually changes things quite a bit, meaning when using partials you have to @use the variables as those variables are no longer globally available.Candelabrum
@Glick yes, you are right :,( LibSass is dead, long live the DartSass! - sass-lang.com/blog/libsass-is-deprecatedVariance
"Dart Sass is 5-10x faster than Ruby Sass and only about 1.5x slower than LibSass" - source ==> This answer should be accepted in 2021.Buchan
for global variables I tend to do a @use 'variables' as * as it won't need the prefix for every variable used.Chlorothiazide
Your explanation is so much clearer and understandable than the SASS documentation! Could you rewrite their DOCS!?Dissimulate
A
450

You can do it like this:

I have a folder named utilities and inside that I have a file named _variables.scss

in that file i declare variables like so:

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

then I have the style.scss file in which i import all of my other scss files like this:

// Utilities
@import "utilities/variables";

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

then, within any of the files I have imported, I should be able to access the variables I have declared.

Just make sure you import the variable file before any of the others you would like to use it in.

Adora answered 11/7, 2013 at 17:1 Comment(9)
Perfect. Just what I meant and needed. Last question: Are all files imported expected to start with an underscore? You underscore your file name, but fail to on the @import declarations.Rashidarashidi
those files are considered partial files and the names have to start with underscores, you leave it out when importing it though. there is a really good article that details why here: alistapart.com/article/getting-started-with-sassAdora
Note that you can declare defaults inside your modules: $black: #000 !default;. The !default thingie prevents the variable from being reset if it already exists.Lysias
One suggestion if you're running Rails 4+, make sure your application.css file is changed to application.scss, then within that file add @import "global.scss"; (which contains your variables e.g $white: #F1FFFA;). Then restart your app ctrl+C, and refresh your webpage.Syringe
Why we have to dump all the variables in a single file? Can't we split and drop them in the respective file that needs them? For example the variables needed for modal dialog can't we place them in _modal.scss?Atman
@vjai, ofcourse you can do that, it won' harm anything. Thank you Joel using this method now and works perfectly. Tired of copying variables from one file to another file.Fuegian
@Atman think about you are working with a dozen of ui component, and now you need to define a main theme color that every component scss files need to reference.Foolery
This answer is no longer the recommended way to re-use variables across multiple files. Please see https://mcmap.net/q/92887/-sass-use-variables-across-multiple-filesGlick
Saw this answer had 399 votes so I had to vote up without even reading. OCDOctal
G
237

This question was asked a long time ago so I thought I'd post an updated answer.

You should now avoid using @import. Taken from the docs:

Sass will gradually phase it out over the next few years, and eventually remove it from the language entirely. Prefer the @use rule instead.

A full list of reasons can be found here

You should now use @use as shown below:

_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;
}

You can also create an alias for the namespace:

_otherFile.scss

@use 'variables' as v;

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

EDIT As pointed out by @und3rdg at the time of writing (November 2020) @use is currently only available for Dart Sass and not LibSass (now deprecated) or Ruby Sass. See https://sass-lang.com/documentation/at-rules/use for the latest compatibility

Glick answered 29/4, 2020 at 11:2 Comment(8)
This should be now the selected answer, since "import" is marked as deprecated and will be removed in the future.Brittan
This is true only for dart-sass that is way less performant than libsass.Variance
@und3rdg I've updated the post to reflect this compatibility point. It's worth mentioning that libsass is now deprecated There is a comment on the github page advising people to use Dart Sass instead for future projects - github.com/sass/libsassGlick
It's an interesting change which actually changes things quite a bit, meaning when using partials you have to @use the variables as those variables are no longer globally available.Candelabrum
@Glick yes, you are right :,( LibSass is dead, long live the DartSass! - sass-lang.com/blog/libsass-is-deprecatedVariance
"Dart Sass is 5-10x faster than Ruby Sass and only about 1.5x slower than LibSass" - source ==> This answer should be accepted in 2021.Buchan
for global variables I tend to do a @use 'variables' as * as it won't need the prefix for every variable used.Chlorothiazide
Your explanation is so much clearer and understandable than the SASS documentation! Could you rewrite their DOCS!?Dissimulate
R
102

This answer shows how I ended up using this and the additional pitfalls I hit.

I made a master SCSS file. This file must have an underscore at the beginning for it to be imported:

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

Then, in the header of all of my other .SCSS files, I import the master:

// 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; }

IMPORTANT

Do not include anything but variables, function declarations and other SASS features in your _master.scss file. If you include actual CSS, it will duplicate this CSS across every file you import the master into.

Rashidarashidi answered 4/1, 2014 at 18:9 Comment(7)
Thanks so much for your comment about the file needing to start with an underscore! I just spent about 3 hours trying to figure out why I was missing a bunch of Foundation styles. Changed the filename of my Foundation settings file to start with an underscore and hey presto! But now when I change the filename back again, it's still working? What the....? Oh well... Sighs and accepts it's now workingCubage
Don't change it back - it's probably 'working' off some generated CSS from your SCSS file when it was working. Just use the underscore. But otherwise, great on getting it working!Rashidarashidi
@Cubage it might work because sass uses cache, so it could be cached. Not 100% sure through.Gallonage
same for sass??Alienist
Depending on your compiler it could be using a 'last known good configuration' approach. I know MVC Core projects won't compile the broken files and you'll have the old file still.Conias
So, if I'm interpreting this correctly, I can't just include the `_master.scss' (variables) file once and have other files "inherit" the variables from some notion of scope? The variable file has to be explicitly included in any file that references the variables?Moorings
Correct you are @rinogo.Rashidarashidi
B
5

In angular v10 I did something like this, first created a master.scss file and included the following variables:

master.scss file:


$theme: blue;

$button_color: red;

$label_color: gray;

Then I imported the master.scss file in my style.scss at the top:

style.scss file:

@use './master' as m;

Make sure you import the master.scss at the top.

m is an alias for the namespace;

Use @use instead of @import according to the official docs below:

https://sass-lang.com/documentation/at-rules/import

Then in your styles.scss file you can use any variable which is defined in master.scss like below:

someClass {

   backgroud-color: m.$theme;

   color: m.$button_color;

}

Hope it 'll help...

Happy Coding :)

Bock answered 17/7, 2020 at 17:45 Comment(0)
L
4

Create an index.scss and there you can import all file structure you have. I will paste you my index from an enterprise project, maybe it will help other how to structure files in 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';

And you can watch them with gulp/grunt/webpack etc, like:

gulpfile.js

// SASS Task

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']);
Linguistic answered 21/7, 2017 at 12:53 Comment(2)
Aren't you supposed to omit the underscore from @import statements?Tamas
Sass '@import' works either way. you can write the URI with or without the underscore. also with or without the '.scss' ending.Hotchpot
P
4

As previously mentioned, the use of @import is discouraged in newer versions of SASS. Use @use "path to SASS partial file" at the top of your file instead.*

You need to import (using @use) the partial SASS file into each SASS file that uses it - not just your main one.

Let's say we have a SASS file called _variables.scss* in a folder called partials that we want to use in header.scss. So in header.scss you write:

@use "partials/variables" as *

Now you can use all the variables defined in _variables.scss* with $variable (no prefix). Alternatively, you can use a namespace (like Christian already mentioned)

@use "partials/variables" as v

to refer to the variables inside _variables.scss* with v.$variable.

* Note that the SASS compiler ignores underscores so that there isn't a separate CSS file generated for each partial SASS file. Instead you can just import them all into your main SASS file with @use.

Pyroxylin answered 31/1, 2022 at 14:35 Comment(0)
P
1

How about writing some color-based class in a global sass file, thus we don't need to care where variables are. Just like the following:

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

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

and then, we can use the background-color class in any file. My point is that I don't need to import variable.scss in any file, just use it.

Premeditation answered 21/12, 2018 at 4:21 Comment(1)
Obvious is a bad idea, you can have many variables and is more clean to keep index with just imports, and every file to have is own propose.Linguistic
B
1

I found a solution for vue3 using vite. If you are using dart-sass, you can get around the global limitation of sass modules by using @forward and @use.

_master.scss

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

_global.scss

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

Then under the vite.config.js configure your css options as

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `
          @use "./<path-to-file>/_globals.scss" as *;
        `,
      },
    },
  },
// etc...
});

As mentioned in the sass docs when importing modules without a namespace

We recommend you only do this for stylesheets written by you, though; otherwise, they may introduce new members that cause name conflicts!

You can then use other @use modules in any other stylesheets or components as following

// component file needing a function module

@use 'functions.scss';
Basic answered 18/6, 2022 at 17:40 Comment(1)
nice answer for who is using viteOutport
L
-1

If you are using it on anything, section here for example purposes, we need to, first of all, use @use instead of @import now, and then we need to use #{colors.$backgroundColor} as an interpolated variable now in the latest version of SASS. Otherwise, it won't work. This is how I use it.

@use "./config/colors"; //Path to your colors or master scss file with the color variables. Notice that we do not use the underscore or the extension when importing it.

@use "./config/colors";
    section {
    background-color: #{colors.$backgroundColor}
    color: #{colors.$textColor} //Interpolated Variable.
    }
Lawton answered 29/1 at 18:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.