Using Angular / Bootstrap, I changed CSS variables at runtime, using this line of code :
document.documentElement.style.setProperty(`--${property.name}`, property.value);
for reference, i used this example to deal with bootstrap SCSS imports : https://blog.wick.technology/runtime-dynamic-bootstrap-theme/
It does work, but some of Bootstrap' styles in bootstrap are broken :
I guess that's because the calc function does not support my dynamic vars :
.btn-primary {
color: hsla(0, 0%, calc(-100 * calc(var(--primary-l) - 58.59375%)), 1);
background-color: var(--primary);
border-color: var(--primary);
}
Is there any way that I can fix this behaviour ? Can I overload a new definition of btn-primary ?
I'm not sure if you already solved your problem or not, but I had the same problem and I feel like I solved it.
I basically decided to create the variables "${variable}-h",${variable}-s", ${variable}-l", which are calculated at runtime when defining the variable, converting the RGB color to the different HSL color components.
Related
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/.
as the question suggested, I want to use custom css colors (with --color*) inside a lighten/darken function. The reason is that I have an Ionic application and I want to change the theme colors dynamically, something like this:
--ion-color-primary: #fff;
--ion-color-primary-rgb: 255, 255, 255;
--ion-color-primary-contrast: #000);
--ion-color-primary-contrast-rgb: 0, 0, 0;
--ion-color-primary-shade: darken(var(--ion-color-primary, 30);
--ion-color-primary-tint: lighten(var(--ion-color-primary, 30);
I am receiving the primary and primary-contrast css properties from other place and I want to be able to set the shade and tint dynamically based on them. With the code above, I received an error saying $color: var(--ion-color-primary) is not a color.
Code snipper
There is a breaking change in Sass since v3.5.0 where you need to write your sass variables and functions within interpolation.
To provide maximum compatibility with plain CSS, more recent versions of Sass require SassScript expressions in custom property values to be written within interpolation. Interpolation will also work for older Sass versions, and so is recommended for all stylesheets.*
Therefore your code should look like this:
$primary: aqua;
--ion-color-primary-shade: #{darken($primary, 30%)};
--ion-color-primary-tint: #{lighten($primary, 30%)};
For the best effect to achieve consider using scale-color() instead of darken/lighten:
The lighten() function increases lightness by a fixed amount, which is often not the desired effect. To make a color a certain percentage lighter than it was before, use scale() instead.**
$primary: aqua;
--ion-color-primary-shade: #{scale-color($primary, $lightness: -30%)};
--ion-color-primary-tint: #{scale-color($primary, $lightness: 30%)};
*For more info about sass interpolation see https://sass-lang.com/documentation/breaking-changes/css-vars.
**For more details on scale-color: https://sass-lang.com/documentation/modules/color#scale
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 am using Angular5 with sass v1.3.2.
I want to be able to change a color that is used extensively in the scss files of my single page app in runtime (not by compiling new files).
The color is defined globally in my _variables.css as:
$brand: #123123;
And for example used as:
h1 {
color: $brand;
}
I learned that I can modify the color if I am using CSS variables such as:
# CSS
:root {
--brand: #123123
}
#JS
document.documentElement.style.setProperty('--brand', '#456456');
# OR
document.querySelector(':root').style.setProperty('--brand', '#456456');
However to be able to do that using SCSS, I needed to use css-vars mixin as such:
$brand: #123123;
:root {
#include css-vars((
--brand: #{$brand},
));
}
And use it as:
h1 {
color: var(--brand);
}
Two problems:
Actually, still --brand is not showing at root.
Also, the CSS generated in <script type="text/css"> by angular-cli does not have --brand anywhere, it is actually compiling the CSS variable into #123123 so the output is:
h1 {
color: #123123;
}
Any ideas about how can I achieve changing a global color in runtime? Or how to get my CSS in :root and then how to get SASS to not compile it?
UPDATE
As #JonUleis has showed, there is no need for using css-var. Now the var --brand shows in the DOM at :root.
However, now color: var(--brand); line still does not show in the CSS, and h1 doesn't have a color style at all.
After updating node-sass to the latest 4.9.0 from 4.8.3, it worked great.
You're likely on an outdated version of node-sass that wasn't yet compatible with the syntax for CSS custom properties.
Here's your example code compiling successfully using Sassmeister without using the css-vars mixin:
The twitter bootstrap code has a lot of CSS properties with a !default at the end.
E.g.
p {
color: white !default;
}
What does !default do?
UPDATE
My bad for not being clear. I am using the SASS part of Bootstrap.
!default is used often in Bootstrap Sass. It is similar to a reverse !important. All of Bootstraps Variables are set using !default to allow the developer to further customize bootstrap. With !default sass will only define a variable if it has not already been set.
This allows for more flexibility.
//Example1 Dress color = red
$auroras-dress-color: blue;
$auroras-dress-color: red;
//Example2 Dress color = red
$auroras-dress-color: blue !default;
$auroras-dress-color: red;
//Example3 Dress color = blue
$auroras-dress-color: blue;
$auroras-dress-color: red !default;
So Why is this important?
Bootstrap is a package. Most people don't edit the Bootstrap source. NEVER UPDATE THE BOOTSTRAP SOURCE. To customize bootstrap you will add your own variable file and compile it with the bootstrap code but never touch the native bootstrap package. Bootstrap sass's page has the full skinny on how to customize and compile it in the documentations.
I don't know why less does not do this. I have not worked much with less and do not know if it has it's own built in variable management.
Example fiddle
https://jsfiddle.net/siggysid/344dnnwz/
Twitter Bootstrap uses LESS as far as I've seen. On the other hand, !default is actually part of Sass, and is used for giving Sass variables ($var) default values, which would make it invalid in your given context, even in Sass.
Besides, I've not been able to find any references to !default in the LESS documentation, and to my knowledge it is exclusive to Sass. Are you sure you found this in Bootstrap's source and not elsewhere? Because I honestly don't remember seeing Sass/SCSS code in Bootstrap's stylesheets.
For what it's worth, the only valid token that starts with ! in CSS is !important, which you may already be aware of.
You can find the following exact definition and a decent explanation in sass-lang website in its doc section (variable) - default value:
Normally when you assign a value to a variable, if that variable already had a value, its old value is overwritten. But if you’re writing a Sass library, you might want to allow your users to configure your library’s variables before you use them to generate CSS.
To make this possible, Sass provides the !default flag. This assigns a value to a variable only if that variable isn’t defined or its value is null. Otherwise, the existing value will be used.
default-values
if that variable isn’t defined or its value is null. Otherwise, the existing value will be used.
Example
case 1: null
// test.sass
$MySize: null
$MySize: 5rem!default // since MySize is "null" so use default
h1
font-size: $MySize
output CSS
h1 {
font-size: 5rem;
}
case 2: undefined
// test.sass
$MySize: 5rem!default // since MySize is "undefined" so use default
h1
font-size: $MySize
output CSS
h1 {
font-size: 5rem;
}
case 3: defined already
// test.sass
$MySize: 30rem
$MySize: 5rem!default // since MySize has been defined. So ignore this setting.
h1
font-size: $MySize
output CSS
h1 {
font-size: 30rem;
}
Here is an example.
$white: white !default;
If you don't define the $white before the code block above, then the $white will be white.
If you define it like this
$white: #eee;
then the $white will be #eee
Here is a link about it in bootstrap-vue,