I want to user var(--darkGrey). So far I have tried this:
$grey: #ddd; // I'd like to remove this line
:root {
--grey: #ddd;
--darkGrey: darken($grey, 55%); // doesn't fail but doesn't work
--darkGrey: darken(#ddd, 55%); // doesn't fail but doesn't work
--darkGrey1: #{darken($grey, 55%)}; // works but I don't like having a Sass var
--darkGrey2: #{darken(var(--grey), 55%)}; // fails: "var(--grey)" is not a color for `darken'
--darkGrey3: #{darken(#ddd, 55%)}; // works but I'd need to use a css var. I have plenty of colors and references
}
I'd say it does not make much sense to use CSS custom property (variable) in Sass function. CSS custom properties could be changed deeper in your CSS structure or even during the runtime, while Sass is available only during compile time. It could not react to such change.
Have a look at hsla() CSS function, which can be used to change lightness of colors during runtime. See article https://sparanoid.com/note/css-variables-guide/.
I am trying to change a variable's value in "../myStyle.scss" file from myComponent.ts . I read that it is impossible to achieve it because sass file are compiled into css by the sass pre-processor and the variable disapears. Isn't there a way to work this around.
My variable is called $theme.
And I want to change it's value.
$theme: #5A352A;
and I want it to become $theme: #ffffff; when the user clicks
You have to work in a different way.
Basically when you compile the angular app , it will generate a css file where it substitute the variable with the value , wherever you used it.
So if you want to achieve a color change you have to create a other variable and other classes and swipe it in your class attributes (this is one way, check also ngStyle and ngClass in angular reference).
For example white-theme/dark-theme (the most common case).
variables -> $black: #00000; $white: #ffffff
Example classes:
.body-dark {
background-color: $black;
}
.body-white {
background-color: $white;
}
and swipe the classes in the html elements.
setDark(){
document.getElementById("bodyId").setAttribute("class","body-dark ")
}
the same for white.
I have created an angular component MyComponent that has a sass and the theme file.
mycomponent.component.scss
#import "../styles/common";
#import 'mycomponent.theme';
.element {
color:$primary
}
in the common.scss, I have imported other files likes variables.scss that contain $primary with predefined or default colour and other theme variables.
and in the mycomponent.theme.scss, I defined the #mixin to update the primary variable
#mixin mycomponent-theme() {
$primary: green ;
}
Now the theme file that creates the final theme.css call this #mixin
#include mycomponent-theme();
but the element class's color is not getting updated to the green color as mixin is updating the $primary variable.
Am I making any mistake? Or what is the other way to achieve this?
Update
Here is the codepen https://codepen.io/ermarkar/pen/wygwYp?page=1&
Your issue has to do with scoping.
The $primary variable that you set to the value green in the mixin mycomponent-theme() is a local variable, therefore, it is only visible to the code that is inside that mixin.
Even though it has the same name as another global variable (I assume it is global), they are different variables.
When you wrote:
.element {
color:$primary
}
Sass used the global variable called $primary, whose value your mixin did not change, the mixin created a local variable with the same name.
There is a very good resource that I recommend you to read that helps understand variable scoping in Sass, much better than I can explain here.
UPDATE:
One thing you could do that I just thought of, is use !global. This keyword lets you manipulate variables in the global scope from within function or mixin blocks.
In your case, if you change your mixin to this:
#mixin mycomponent-theme() {
$primary: green !global;
}
Then the mycomponent-theme() mixin will change the global $primary variable.
So here's kind of a weird thing with the custom.scss file in bootstrap that I discovered tonight and wondering if I am missing something. Let's say I set the color $blue to a custom value (#000 in this case just to make it easy to read) and remove the !default flag in _custom.scss as I'm supposed to. In the _variables.scss file, the color $brand-primary is set to $blue, with a !default flag. Then, the $btn-primary-bg is set to $brand-primary, also with a !default flag. So, my thinking is if I set:
$blue: #000000;
in the custom.scss file, it should then cascade down to any variable using $blue, making it so that:
$brand-primary: $blue; set to #000 and then
$btn-primary-bg: $brand-primary; also set to #000000
Well, turns out I have to list all 3 of those instances in the custom sass file and remove their !default flag before they would change to the custom color.
So instead of my custom sheet just having one line
$blue: #000000;
it needs to be
$blue: #000000 ;
$brand-primary: $blue;
$btn-primary-bg: $brand-primary;
before that custom color gets applied to those classes.
Am I missing something here? Shouldn't we just have to set the custom color once and then any variable referencing it would also reference that custom color? Seems inefficient to me at this point.
[enter link description here][1]There is no problem with the variables have been defined. Probably you need to change the way you have used them in HTML. Have a look at below example which has been provided based on your defined variables. I would suggest remove "$blue" variable and define the color directly for "$brand-primary" variable!
[1]: https://jsfiddle.net/negin/t36ep4e8/
EDIT: This question was marked as a duplicate of this one, but see the addendum near the end of this answer to see what that question doesn't ask, and what the answer doesn't answer.
I'm working on a web app that uses Bootstrap 3. I have a basic 3-layer override architecture, where 1) Bootstrap's _variables.scss contains the core variables, 2) _app-variables.scss contains the base app variables that override Bootstrap's _variables.scss, and 3) _client-variables.scss contains client-specific customizations that override _app-variables.scss. Either #2 or #3 (or both) can be blank files. So here's the override order:
_variables.scss // Bootstrap's core
_app-variables.scss // App base
_client-variables.scss // Client-specific
Simple enough in theory, but a problem arises because of what I'll call "variable dependencies" -- where variables are defined as other variables. For example:
$brand: blue;
$text: $brand;
Now, let's say the above variables are defined in _variables.scss. Then let's say in _app-variables.scss, I override only the $brand variable to make it red: $brand: red. Since SASS interprets the code line by line sequentially, it will first set $brand to blue, then it will set $text to blue (because $brand is blue at that point), and finally it will set $brand to red. So the end result is that changing $brand afterwards does not affect any variables that were based on the old value of $brand:
_variables.scss
---------------------
$brand: blue;
$text: $brand; // $text = blue
.
.
.
_app-variables.scss
---------------------
$brand: red; // this does not affect $text, b/c $text was already set to blue above.
But obviously that's not what I want - I want my change of $brand to affect everything that depends on it. In order to properly override variables, I'm currently just making a full copy of _variables.scss into _app-variables.scss, and then making modifications within _app-variables from that point. And similarly I'm making a full copy of _app-variables.scss into _client-variables.scss and then making modifications within _client-variables.scss at that point. Obviously this is less than ideal (understatement) from a maintenance point of view - everytime I make a modification to _variables.scss (in the case of a Bootstrap upgrade) or _app-variables.scss, I have to manual trickle the changes down the file override stack. And plus I'm having to redeclare a ton of variables that I may not even be overriding.
I found out that LESS has what they call "lazy loading" (http://lesscss.org/features/#variables-feature-lazy-loading), where the last definition of a variable is used everywhere, even before the last definition. I believe this would solve my problem. But does anyone know a proper variable-override solution using SASS?
ADDENDUM:
Here's one technique I've already thought through: include the files in reverse order, using !default for all variables (this technique was also suggested in the answer to this question). So here's how this would play out:
_app-variables.scss
---------------------
$brand: red !default; // $brand is set to red here, overriding _variables.scss's blue.
.
.
.
_variables.scss
---------------------
$brand: blue !default; // brand already set in _app-variables.scss, so not overridden here.
$text: $brand !default; // $text = red (desired behavior)
So that solution is almost perfect. However, now in my override files, I don't have access to variables defined in Bootstrap's _variables.scss, which I would need if I wanted to define my variable overrides (or my own additional custom variables) using other Bootstrap variables. For example, I might want to do: $custom-var: $grid-gutter-width / 2;
Solved, but I don’t know from which version this works. I believe the solution could have always been available. Tested on:
> sassc --version
sassc: 3.2.1
libsass: 3.2.5
sass2scss: 1.0.3
We are going to use a simplified environment, so filenames do not match with Bootstrap’s.
Challenge
Given a framework we do not control (for example installed only on the Continuous Integration environment and not available in our machines) that expresses SCSS variables in the following manner:
// bootstrap/_variables.scss
$brand-primary: #f00 !default;
$brand-warning: #f50 !default;
$link-color: $brand-primary !default;
And given a file in that same framework that uses the variables:
// bootstrap/main.scss
a:link, a:visited {
color: $link-color;
}
The challenge is:
Include the framework in your own application’s SCSS in such a way that
variables’ dependencies in the framework are preserved and honors;
you can depend in on the default values but still be able to change the results on the framework dependencies.
More precisely:
Include the framework in your application’s SCSS in such a way that $brand-color will always be the inverse of $brand-warning, whatever its value is in the framework.
Solution
The main file would look like this:
// application.scss
#import "variables";
#import "bootstrap/variables";
#import "bootstrap/main";
And your variables file would look like this:
// _variables.scss
%scope {
#import "bootstrap/variables";
$brand-primary: invert($brand-warning) !global;
}
Results:
> sassc main.scss
a {
color: blue; }
Explanation
The %scope part is not something magic of SCSS, it’s simply a hidden class with the name scope, available exclusively for later extensions with #extend. We are using it just to create a variable scope (hence the name).
Inside the scope we #import the framework’s variables. Because at this moment there’s no value for each variable every variable is created and assigned its !default value.
But here’s the gimmick. The variables are not global, but local. We can access them but they are not going to pollute the global scope, the one that will be later used to derive variables inside the framework.
In fact, when we want to define our variables, we want them global, and indeed we use the !global keyword to signal SCSS to store them in the global scope.
Caveats
There’s one major caveat: you cannot use your own variables while you define them.
That means that in this file
%scope {
#import "bootstrap/variables";
$brand-primary: black !global;
#debug $brand-primary;
}
The #debug statement will print the default value defined in bootstrap/_variables.scss, not black.
Solution
Split variables in two parts:
%scope {
#import "bootstrap/variables";
$brand-primary: black !global;
#debug $brand-primary;
}
#debug $brand-primary;
The second #debug will indeed correctly print black.
With Bootstrap 4 or bootstrap-sass all variables set in the _variables.scss with the !default flag.
Therefore, if you set a variable before bootstrap's _variables.scss is included, when it is included, the value from _variables.scss will be ignored.
So my sass entry file might look like this ...
#import "bootstrap-overrides";
#import "bootstrap/scss/bootstrap-flex";
#import "mixins/module";
In alpha 6 of Bootstrap 4, all variables in _variables.scss can be overridden in _custom.scss, in the way that mryarbles describes.
However, the overrides do not cascade to other elements, because the inclusion order is:
#import "variables";
#import "mixins";
#import "custom";
When I change this to
#import "custom";
#import "variables";
#import "mixins";
it works as expected.
The _custom.scss file in BS4 dev branch has been removed. Try to reorder your imports with this order:
Setup
#import "client-variables";
#import "app-variables";
#import "boostrap";
#import "app-mixins";
#import "client-mixins";
Make sure to copy the content of boostrap variable file _variables.scss to app-variables and client-variables. Leave the !default beside each variable to allow further override.
Explanation
All bootstrap variables are declared with !default. From Sass reference:
You can assign to variables if they aren’t already assigned by adding the !default flag to the end of the value. This means that if the variable has already been assigned to, it won’t be re-assigned, but if it doesn’t have a value yet, it will be given one.
Bootstrap will respect all variables already defined on top making the app_variables with higher priority and client_variables with highest priority.
You need to copy all the variable declarations from bootstrap _variables into app-variables and client-variables so you can have a custom variable as you wanted. (Disadvantage is that it is harder to maintain on every bootstrap update)
All variables are now available in your app-mixins and client-mixins