338

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?

dthree
  • 19,847
  • 14
  • 77
  • 106
  • I am pretty sure that is not possible, I tried the same thing awhile ago and could not get it to work. – DrCord Jul 11 '13 at 16:45
  • 11
    @DrCord on the contrary it is a central feature of SASS: http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#partials – Ennui Jul 11 '13 at 17:23
  • 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. – DrCord Jul 11 '13 at 21:52

8 Answers8

442

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.

dthree
  • 19,847
  • 14
  • 77
  • 106
Joel
  • 5,300
  • 2
  • 14
  • 13
  • 8
    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. – dthree Jul 11 '13 at 17:04
  • 62
    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: http://alistapart.com/article/getting-started-with-sass – Joel Jul 11 '13 at 17:08
  • 7
    Note that you can declare [defaults](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#variable_defaults_) inside your modules: `$black: #000 !default;`. The `!default` thingie prevents the variable from being reset if it already exists. – Andrey Mikhaylov - lolmaus Jul 11 '13 at 18:48
  • 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. – seanriordan08 Dec 04 '16 at 03:44
  • 2
    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? – VJAI Jun 23 '17 at 13:48
  • @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. – grimesd Sep 01 '17 at 16:44
  • @VJAI 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. –  Feb 10 '18 at 04:52
  • 10
    This answer is no longer the recommended way to re-use variables across multiple files. Please see https://stackoverflow.com/a/61500282/7513192 – whiscode May 13 '20 at 14:32
  • Saw this answer had `399` votes so I had to vote up without even reading. ***OCD*** – vsync Jan 10 '22 at 16:16
210

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

whiscode
  • 2,301
  • 1
  • 12
  • 7
  • 14
    This should be now the selected answer, since "import" is marked as deprecated and will be removed in the future. – Timtim Jun 04 '20 at 13:32
  • 1
    This is true only for dart-sass that is way less performant than libsass. – undg Nov 04 '20 at 13:38
  • @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 - https://github.com/sass/libsass – whiscode Nov 04 '20 at 13:59
  • 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. – Rob Jan 20 '21 at 22:35
  • @whiscode yes, you are right :,( LibSass is dead, long live the DartSass! - https://sass-lang.com/blog/libsass-is-deprecated – undg Feb 09 '21 at 13:32
  • "Dart Sass is 5-10x faster than Ruby Sass and only about 1.5x slower than LibSass" - [source](https://sass-lang.com/blog/announcing-dart-sass) `==>` This answer should be accepted in 2021. – s3c May 26 '21 at 11:54
  • 1
    for global variables I tend to do a `@use 'variables' as *` as it won't need the prefix for every variable used. – theking2 Dec 23 '22 at 08:18
101

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.

dthree
  • 19,847
  • 14
  • 77
  • 106
  • 5
    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 working* – poshaughnessy Jun 09 '15 at 15:18
  • 5
    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! – dthree Jun 09 '15 at 15:32
  • @poshaughnessy it might work because sass uses cache, so it could be cached. Not 100% sure through. – PeterM Apr 28 '16 at 09:30
  • same for sass?? – MartianMartian Feb 28 '18 at 15:51
  • 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. – Ben Sampica Sep 27 '18 at 14:22
  • 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? – rinogo May 01 '20 at 20:35
  • 2
    Correct you are @rinogo. – dthree May 02 '20 at 15:52
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 :)

Cristian
  • 654
  • 1
  • 13
  • 30
Faraz Ahmed
  • 61
  • 1
  • 5
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']);
Carnaru Valentin
  • 1,690
  • 17
  • 27
  • 1
    Aren't you supposed to omit the underscore from @import statements? – Quantum7 Dec 21 '17 at 13:17
  • 2
    Sass '@import' works either way. you can write the URI with or without the underscore. also with or without the '.scss' ending. – Pony Jun 04 '18 at 08:18
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.

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.

robere2
  • 1,689
  • 2
  • 16
  • 26
gary gao
  • 203
  • 2
  • 7
  • 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. – Carnaru Valentin May 06 '19 at 08:00
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';