In bootstrap 4 you can define and/or override default colors using the following array: (as documented here)
$theme-colors: (
"primary": #001122, /*override*/
"color-1": red, /*new color*/
"color-2": black, /*new color*/
"color-3": white /*new color*/
);
I want to make custom theme colors for different users. Users can choose different color palettes which I have defined based on the class of the body.
I made a new file to make my own styles, defining my theme colors in CSS variables in the body tag:
body {
&.color-pallette-red {
--theme-color-1: red;
--theme-color-2: black;
--theme-color-3: white;
color: var(--theme-color-1); /*red*/
}
&.color-pallette-yellow {
--theme-color-1: yellow;
--theme-color-2: black;
--theme-color-3: white;
color: var(--theme-color-1); /*yellow*/
}
}
But in this way, the bootstrap colors are of course not overwritten…
I tried to paste my CSS variables in the bootstrap array mentioned earlier, to make sure that bootstrap used my colors:
$theme-colors: (
"color-1": var(--theme-color-1),
"color-2": var(--theme-color-2),
"color-3": var(--theme-color-3)
);
But this returns Error: $color2: var(--theme-color-1) is not a color. @return mix($color-base, $color, $level * $theme-color-interval);
after running the compiling script. So bootstrap/compiler didn’t recognize my CSS variables as a color…
Summarized what I want is: Change bootstrap colors based on body class. Does anyone know a way to achieve this?
3
Answers
You can’t set CSS variables in the maps directly, because that variable would not be compiled at the time as SASS is a preprocessor, additionally bootstrap turns around and converts those theme KVPs into
:root
variables anyways, so you’re essentially doing the same thing twice. One way around this is you can just tap into the map itself via genericSASS
methods:Once you have set that particular KVP, it will then be available globally to use elsewhere.
At this point, it’s arbitrary to use CSS
var()
, but just to cover all my bases, you can set the theme, and then alter the variable, as opposed to re-setting & callingtheme-color("color-2")
.A full example of this would be the following:
Note, the example also demonstrates if one theme sets the variable and others don’t. The theme color you choose is invalid and the property reverts to inherit.
codeply demo
I like my other answer, but I would also like to offer another solution, provided that one doesn’t fit the project scopes needs. Another option, and I think more direct to your needs, is you could just cascade your style sheets. Assuming a project tree resembles the following:
Where
index.html
:Where
main.css
:Where
themes.sass
:That way your CSS variables have had a chance to be compiled. I tested on a node.js server, so you should change the import statement as needed
Why you cannot use CSS variables for colors in SASS
The reason you are not able to use CSS variables for colors are functions like
darken()
andlighten()
in SASS. You can imagine that the computer will not know what to do when it gets the instruction:darken( var(--color), 20%)
; You cannot modify a value you don’t know about.What if we just don’t use functions that change colors?
In fact that should actually work. The bootstrap library has scss-files that use those functions. You could go through all the bootstrap code and remove the functions that modify colors. Of course that would be a bit of work. Updating bootstrap in the future would cause your site’s styling to mysteriously crash and someone will be very mad at you. So this option is not a good idea.
But…But… If CSS can do it you can with SASS?
YES! This is the answer. And it’s going to be quite a bit of work. If you set the colors using another variable, you can use a SASS variable like
--color
for those colors. E.g.:Luckily the bootstrap 4 developers have done a pretty good job at keeping their selectors simple, so it won’t be too hard to overwrite. Remember to load your CSS after the bootstrap css. You may want to search the bootstrap scss files for the SASS variable you are overriding to make sure you cover all cases.
Goodluck!