SASS - use variables across multiple files - css

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?

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.

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

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.

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 :)

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']);

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.

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.

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';

Related

SCSS Variable not applying globally

I have a variable and gallery partial: _variables.scss, _gallery.scss
When I import the variables file, which contains only one line $primary: #e0291a;, it works in the main style.scss file, but not in the _gallery.scss file.
My project is only going to grow, but do I really need to import the variables file in every single subsequent partial file?
I'm using VSCode Live Sass Compiler. The variables work with a custom webpack/laravel mix script I've set up a few years back, but not with this extension.
Is there a way to streamline the variable import without adding the line in every single scss file?
style.scss (main file):
#use 'variables';
#use 'gallery';
_variables.scss:
$primary: #ffffff;
_gallery.scss:
#gallery {
background-color: $primary // <--- Throws error of undefined variable
}

Global scss variables for Angular components without importing them everytime

I do already have SCSS variables defined in src/styles/settings/_variables.scss and I am importing them into src/styles.scss, but still these variables aren't available for every single component.
Is there any way to make a global file which holds all SCSS variables for the rest of my components? Because writing #import in every single component .scss file it is very frustrating, especially if I have many nested components.
I know, there is a lot of similar questions, but it seems like they're all outdated and do not relate to the recent versions of Angular.
I use Angular 7.3 with CLI.
You just need to add a little more config, so where you are declaring your global variables, you need to wrap it up in :root{}. So in src/styles/settings/_variables.scss.
:root
{
--blue: #00b; // or any global you wish to share with components
}
Then when you use them in the SCSS you will need to access them like so.
.example-class {
background-color: var(--blue)
}
To add to this regarding comments, this method can use mixins, #media and keyframes and is not limited to just colours / font. That was an example.
From my understanding you need a global file src/assets/style/global and then to import each scss file into there where you are defining them like so.
#import 'filename';
If you dont want global variables to be used in within a component look when you have the globals working. Look into ViewEncapsulation, as this can be used to ignore them.
Is there any ways to make global file with scss variables available for all components?
Without importing global file everytime in each component, you want those sass variables been available, it's not possible.
The way it works in SASS, if using partials to better organize code, you can apply #import directive for referencing. So if there're some sass variables in shared/_variables.scss:
$lightslategray: #778899;
$darkgray: #A9A9A9;
and these variables need to be used in another stylesheet, stylesheet with them must be #import-ed into it firstly:
// Shared
#import "shared/variables";
.content {
background: $lightslategray;
}
In Angular it works in a similar way (related referencing external stylesheet). So if you need some sass variables, mixins or functions to be used by a particular component.scss, there is no other clean way, but to reference them in that component.scss using #import directive. To ease the task, you can create a file src/_variables.scss and use syntax like this in your component.scss:
#import “~variables.scss”;
step one : go to custom scss file (shared/css/_variable.scss) and write this part
:root{
--color-text: red;
--color-btn-success: green;
}
after go to style.scss (this is main file) and import this file :
#import './shared/css/Variables';
now you can use variables in all components with this Syntax:
.sample{
color : var(--color-text);
}
Easily possibe to access sass style(s) from a global file with two steps.
Add folder path of the style files to includePaths array in angular.json file.
Import style file by file-name in any component.
let say your files and folder structures is as follows: src > my-styles-folder > var.scss
angular.json
"architect": {
"build": {
...
"options": {
"stylePreprocessorOptions": {
"includePaths": [
"src/my-styles-folder" // add path only, do not include file name
]
},
"styles": [
...
]
}
...
}
}
some-component.scss
#import "var"; // var.scss
mat-toolbar {
height: $toolbar-height;
}
In angular 8 work for me.
In your _variable.scss file you have to add:
:root{--my-var:#fabada}
After that go in your angular.json and add this in "styles":
{"input":"yourPath/_variables.scss"}

How do I compile my .scss file into multiple .css files depending on the variables

I have a simple gulp build to compile my .scss files:
gulpfile.js:
gulp.task('sass', function() {
return gulp.src('app/assets/scss/**/*.scss')
.pipe(gulp.dest('app/assets/css'))
});
...
index.scss:
$brand-primary: #b0b0b0;
// $brand-primary: #b1b1b1;
// $brand-primary: #b2b2b2;
...
In index.scss I have multiple versions of the $brand-primary variable I want the file to compile with, e.g. I want gulpfile.js to automatically create multiple versions of index.scss depending on the $brand-primary variable: index-1.css, index-2.css, index-3.css, etc. with the $brand-primary value equal to #b0b0b0 first, then #b1b1b1, then #b2b2b2 accordingly.
The idea is to create multiple color options for my template without manually recompiling it for each color.
PS: I am aware of CSS variables, however those won't work with color function like darken($brand-primary, 10%);
It would be very hard to do what you ask purely programatically. I'm not even sure it's possible.
Why don't you just create 3 index.scss files each with different $brand-color and and then import everything else in them. Or even better make another file which will import all of your other *.scss files and then just import that file and color in each index file. So your index files would look like this:
$brand-primary: #b0b0b0;
#import 'style';
and _style.scss would have all of your other scss dependencies.

Sass import partial content in another sass file

I would like to use sass in my new project, but I can't find a better way for cross file usage. Here is the example
/*a.scss*/
#mixin mixA{
....
}
.classInA{
...
}
/*b.scss*/
#import 'a'
....
I want to use the mixA without having other scss(such as classInA) being imported into b.scss, how can I do it?
One way to do it is to put all your mixins in a general mixins file, then, import that file into another general file where you import all the SCSS (or SASS) files.
/*mixins.scss*/
//Here goes all your mixins
/*main.scss*/
#import 'mixins';
#import 'header';
#import 'footer';
And import the mixins you want in the files needed.
If you want to import other sass file simply do :
#import 'path/sass-file';
#import 'path/sass-file';
#import 'path/sass-file';
If you would like extend any of already created class in your scss you can do it like this :
.new-custom-class {
#extend .custom-class;
/* you can add some options in here also */
}

Import css/scss file into a class

I have a problem. I'm using vaadin inside liferay. I've successfully written a fully responsive (yeah, tables too) theme for vaadin, based on bootstrap. Now I'm importing it to liferay. Everything went fine 'till I needed to upgrade Liferay, where their new responsive theme is using same classes name as bootstrap, but with different behaviour (sad, very sad face).
The solution I've thought so far is to apply a class to the vaadin compiled css, like:
.daVaadinTheme {
#import bootstrap.css;
}
so the content will be compiled like:
.daVaadinTheme h1.insideTheFile{
}
.daVaadinTheme h2.insideTheFile{
}
But, as you may figured out, is not obviously working.
Do you have any solution?
Read carefully! This is NOT a duplicate of the answer you've posted. I'm trying to import a CSS file inside a CSS/SCSS class of another file, like the example I've written above. My problem is not to simply import a CSS file inside another one...
SOLUTION: (kudos to Mathias Jørgensen)
using #import from another scss file:
in test.scss:
.daVaadinTheme{
#import "bootstrap.scss";
}
Name your inner file with an underscore, and ending in scss. .Yes, even if it's plain css, i.e. foo.css → _foo.scss
Have an outer File like so:
#main .content { // if that's, where you want them to rule only
#import 'foo';
}
Reasons:
import only works with scss
underscore-files are glady skipped by sass (also as in gulp.src(<some wildcards).sass())
if you have no influence in your repo about the css filename whatsoever. or it's a major pain on upgrades, consider using a symbolic link under an .scss extension...
You need move your code into mixin:
// botstrap.scss
#mixin bootstrap {
h1.insideTheFile{
}
h2.insideTheFile{
}
}
Then, you can import normal:
// test.scss
#import "bootstrap"; // No extension
#include bootstrap; // The name of "mixin"
or with context:
// test.scss
#import "bootstrap"; // No extension
.daVaadinTheme {
#include bootstrap; // The name of "mixin"
}
If you want to add certain styles to a class using sass/scss I think what you're looking for is
.myClass { #import bootstrap.css; }

Resources