Sign in

Change website brand color dynamically

Hi, i am Abdullah al fahad. Recently I facing a problem with changing the brand color dynamically of a web application. Laravel, Nuxt, Docker have been used has as technology. This application used SCSS for describing the presentation of application pages, including colors, layout, and fonts, etc., and HEX color system used in the whole application.

I have selected brand colors in my database like brand_color:{primary:'#36ff24', secondary:'#36ff24'} and I have to change everywhere I use primary and secondary colors in SCSS.

We all know in SCSS set variables like $primary:#36ff24 and use like h1{color:$primary}. These SCSS variables can’t access outside of the SCSS file, and SCSS can’t access data from the database or any API response.

But javascript can access CSS variables and update value. In SCSS we can write any CSS code. So I change all my SCSS color variables to CSS variable like $primary:#36ff24 ... -> :root{--primary:#36ff24, ...} and use like h1{color:var(--primary)}.

Now the real problem starts here.

SCSS has some helpers for make color variations like darken($primary,10%), lighten($primary,10%) these helpers can’t accept CSS variables darken(var(--primary),10%) or any color code darken(#36ff24,10%), and I used these helpers in many places of my application, also I need these variations.

To resolve this I change my color system HEX to HSL hsl(hue,saturation,lightness).In here I split hsl(115,100%,57%) To :root{--primary-h:115,--primary-s:100%,--primary-l:57%} . I split this because for making darken and lighten we have to change that 3rd value of hsl(hue,saturation,lightness). If you increase the lightness value, you get a light color of the selected color. And if you decrease the lightness value, you get a darken color of the selected color. To make darken and lighten color variation I make SCSS function and use it in SCSS h1(color: generateDarken(primary,10%).generate

@function generateDarken($name, $l:10%) {
@return #{unquote(“hsl(var( — #{$name}-h), var( — #{$name}-s), #{calc(var( — #{$name}-l) — #{$l})})”)};
}
@function generateLighten($name, $l:10%) {
@return #{unquote(“hsl(var( — #{$name}-h), var( — #{$name}-s), #{calc(var( — #{$name}-l) + #{$l})})”)};
}

The second problem is making rgba(red,green,blue,alpha) color. In SCSS you can use any color variable in rgba() like rgba($primary, .5) . In here SCSS convert your color variable to RGB color. But in rgba() you can’t use any color code rgba(#34ff24, .5) or CSS variable rgba(var(--primary, .5) . But I have to use the CSS variable here. Because I can only change CSS variable value by javascript.

To resolve this problem I make an SCSS function with hsla(hue, saturation,lightness, alpha) . In hsla() we can control alpha value like rgba(). Used in SCSS button{box-shadow: 0 10px 10px 2px generateHsla(primary,.5)}.

@function generateHsla($name,$o:1) {
@return hsla(var(--#{$name}-h), var(--#{$name}-s), var(--#{$name}-l), $o)
}

Finally, now we able to change color dynamically. When I pick a color from HTML I picking the HEX color code. So I have to convert it to HSL. To convert HEX to HSL, I make a javascript function. 🤫Actually, I copied this function from another source and make some modifications.

hexToHsl(H){
let r = 0, g = 0, b = 0;
if (H.length == 4) {
r = "0x" + H[1] + H[1];
g = "0x" + H[2] + H[2];
b = "0x" + H[3] + H[3];
} else if (H.length == 7) {
r = "0x" + H[1] + H[2];
g = "0x" + H[3] + H[4];
b = "0x" + H[5] + H[6];
}
// Then to HSL
r /= 255;
g /= 255;
b /= 255;
let cmin = Math.min(r, g, b),
cmax = Math.max(r, g, b),
delta = cmax - cmin,
h = 0,
s = 0,
l = 0;
if (delta == 0)
h = 0;
else if (cmax == r)
h = ((g - b) / delta) % 6;
else if (cmax == g)
h = (b - r) / delta + 2;
else
h = (r - g) / delta + 4;
h = Math.round(h * 60); if (h < 0)
h += 360;
l = (cmax + cmin) / 2;
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
return {h, s, l};
}

We can change the CSS variable value when all CSS loaded. I am using Vue, I decide to make changes with the mounted hook. because in Vue when everything is loaded then mounted hook executes.

mounted(){
const {h, s, l} = hexToHsl('#34ff24')
document.documentElement.style.setProperty("--primary-h", h);
document.documentElement.style.setProperty("--primary-s", s + '%');
document.documentElement.style.setProperty("--primary-l", l + '%');
}

You can also make changes in created() or anywhere by checking the process.client if you are using nuxt. When start processing client you can access your CSS variables by document.documentElement.style .