Samuel Martins I am a full-stack developer who loves sharing the knowledge accumulated over the years with people. The different technologies that I have encountered through my journey allows me to relate to beginners and seniors alike. I write about all things tech.

How to add dynamic colors with CSS

4 min read 1244

CSS Dynamic Colors

When most developers see the word “dynamic”, the first thing that comes to mind is JavaScript. However, most of the time, you can implement dynamic functionalities using only CSS. For example, think about implementing a responsive header with a toggle button, or affecting one div through a click or hover event on a different div or element. This is possible using only CSS.

In this article, we’ll learn how to add dynamic colors to our application using only CSS. Dynamic colors are defined by a content editor, meaning that the design system might not necessarily know about the color beforehand.

We can implement the dynamic colors feature using CSS variables, which are supported in most modern browsers, excluding Internet Explorer 11. There are several different ways that you can add and manipulate dynamic colors with CSS, in this article, we’ll explore a few:

Let’s get started!

Using transparency

If you’ve worked with colors before in CSS, you may already be familiar with creating colors using custom properties and the alpha channel. Just to jog your memory, consider the code below:

:root {
--color: 255 255 0;
}

.selector {
background-color: rgb(var(--color) / 0.5);
}

Transparency CSS Colors Example Output

The code above covers the simplest way of creating custom color properties, but this approach is flawed. It requires you to define the custom property color in a color space that supports the alpha channel in its function, like the rgb(), rgba(), and hsla().:

:root {
--color-rgb: 255 255 0;
--color-hsl: 5 30% 20%;
}

.selector {
background-color: rgb(var(--color-rgb) / 0.5);
background-color: hsl(var(--color-hsl) / 0.5);
}

Main DIV CSS Alpha Channel

Therefore, you cannot allow a custom property’s color value to switch from one type to another. In this context, I’m using switch, which is sort of like typecasting in languages like JavaScript and Python.

A great example of that impossibility would be something like the following:

:root {
--color: #fa0000;
}

.selector {
/*
Trying to convert a HEX color to an RGB one doesn't work
This snippet will not work. this just return a blank white background
*/
background-color: rgb(var(--color) / 0.5);
}

CSS Switch Statement

With that said, having dynamic colors in CSS using HEX color values is not really possible. Even if you can specify the alpha channel for the HEX color, for example, #FA000060, you can only do so in a declarative way. CSS doesn’t really have string concatenation, meaning you cannot dynamically specify the alpha channel:

:root {
--color: #fa0000;
}

.selector {
/* You can’t dynamically specify the alpha channel. This will still not do anything */
background-color: var(--color) + "60";
}

Trying to create dynamic colors with named colors is not advisable due to a lack of instructions. However, relative colors can create dynamic colors in a more powerful and usable way. 

Relative colors

With relative colors, you can declare a custom property with a value of any color type, namely rgb, rgba, hsla, hsl, hex, etc. You’ll be able to convert it to any other type on the fly.

If you ask me, this is, by far, the best way to add and manipulate dynamic colors. Below is an example of how you would do this:

/* - - - - - - - - - - - - Using hex Colors - - - - - - - - - - - - - - */
:root {
  --color: #fa0000;
}

.selector {
  /* can’t do this */
  background-color: rgb(var(--color) / 0.5);

  /* can do this */
  background-color: rgb(from var(--color) r g b / .5);
}

Most people would attempt to follow the syntax on line 8, however, it won’t work. Instead, the correct syntax on line 11 shows how relative colors are used to make or manipulate dynamic colors. This methodology even works with the normal named colors:

/* - - - - - - - - - - - - Using Named Colors - - - - - - - - - - - - - - */
:root {
  --color: red;
}

.selector {  
  background-color: rgb(from var(--color) r g b / .5);
}

Like I mentioned earlier, this is sort of the same thing that happens with languages like JavaScript and Python when it comes to typecasting or type coercion.

Using the calc() function

Although adding dynamic colors works using the alpha channel, you are bound to realize that it has its drawbacks. Think of it this way. Transparent colors won’t always blend into white. Instead, they blend into the colors on which they sit.

Basically, you can get a lighter version of a color, but it won’t be consistent throughout your page because the color it sits on will impact its appearance. To ensure that the color it is sitting on doesn’t affect it, you’d need to use the opaque version of the lighter or darker color.

Previously, you would handle this in CSS by being specific in your custom property definition and defining all the channels you have individually:

:root {
  /* Define individual channels of a specific color */
  --color-h: 0;
  --color-s: 100%;
  --color-l: 50%;
}

.selector {
  /* Dynamically change individual channels */
  color: hsl(
    var(--color-h),
    calc(var(--color-s) - 10%),
    var(--color-l)
  );
}

CSS Calc Function

However, you can already tell that your code is going to get really wordy really fast. And then again, values like HEX are not really supported. With CSS relative colors, you can handle this using the calc()function, and it will result in the same color as in the image above:

:root {
  --color: #ff0000;
}
.selector {  
  color: hsl(from var(--color) h calc(s - 10%) l);
}

You’ll notice a significant improvement over the wordy code.

Filter percentage value

These are just the main ways you’d add dynamic colors with pure CSS. But, in addition to these, you can always go back to manipulating color by using the good old filter percentage value.



The filter: brightness(x%) function is used to dynamically change color by percentage. The x% value will manipulate the color to that specific value. This method for working with colors is less popular because it affects the specific element, meaning that some parts of your page may appear brighter than others.

Additional methods in SASS and JavaScript

If you are looking to go beyond CSS, you can look into SASS and JavaScript. SASS comes with color manipulation functions right off the bat, including:

lighten() and >darken()
complement()
hue()
mix()
contrast-color()

I could try and expand further on these, but it would be outside the scope of this particular piece. That being said, for a better understanding, you can read further on SASS color functions in their documentation.

When adding color dynamically with JavaScript, you need only work with the DOM and the CSS color property. You have options like changing the color on page load, five seconds after page load, and more. You’re basically trying to create responses to events that the DOM can listen for, things like clicks, mouse scrolls, and key up or down. Really, the possibilities are endless.

Conclusion

You don’t actually need dynamic colors, but then again, you sort of do. It all comes down to your preference, the current task at hand, and how much code you want to write. Look at it this way, you don’t need dynamic colors if you aren’t doing anything dynamic with them. For example, think about things like dark mode or color changes with mouse movement.

You don’t need JavaScript to make your CSS colors dynamic. You need only take advantage of dynamic colors. Knowing how to create and manipulate them is a great tool to have in your CSS bag of tricks. Try it out and remember to have fun. Happy coding!

Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — .

Samuel Martins I am a full-stack developer who loves sharing the knowledge accumulated over the years with people. The different technologies that I have encountered through my journey allows me to relate to beginners and seniors alike. I write about all things tech.

One Reply to “How to add dynamic colors with CSS”

  1. I feel like some context is missing from the article. Where does the keyword `from` come from? This doesn’t seem to work, and I can’t find any reference to it in the CSS specs.

    `–color: hsl(from var(–color) h calc(s – 10%) l);`

Leave a Reply