Patrick Desjardins Blog
Patrick Desjardins picture from a conference

How to use CSS variables in React components and CSS files

Posted on: 2022-10-27

If you want to define at a single place values to use inside your React components and inside CSS files, you need a central location. I enjoy keeping colors and styles all in CSS files (or CSS modules).

CSS

Settling into a solution of defining all values in CSS as the source of truth is technically possible.

The first step is to define your variables. For example, you can specify a background color at the :root. Of course, it could be at another level, but I prefer setting global variables at the highest level possible.

:root {
  --button-background-color: #c0c0c0;
}

TypeScript

The second step is to extract the value in TypeScript (or JavaScript), which React can use.

const buttonBackgroundColor: string = getComputedStyle(
  document.documentElement
).getPropertyValue("--button-background-color");

Caveats

Like most solution, there is some details that must be considered. First, the value extracted is a string. In the case of the color, it is fine, but if you pull a position or dimension, you will need to parse the string into a number.

The second caveat is that you may miss type the name of the variable name. Is it --button-background-color or --button-bg-color? Providing the wrong name results to an empty string.

Code Sandbox: Extracting Values

The code example provides an easy but not practical example of reading a variable and using it in a style. Indeed, in the real world, we would not rely on style and only on CSS for that purpose. Nonetheless, it shows that we are using the variable value to set the color to the button background.

Theme with Conditional CSS Variables Value

A pattern that I like is to define a variable depending on a theme. The theme is selected by assigning a value to an attribute, and the CSS check if the attribute is a specific value.

html {
  --button-background-color: #c0c0c0;
}

html[data-theme="dark"] {
  --button-background-color: #7fffd4;
}
// Get current theme value (light or dark)
const currentTheme = document.documentElement.getAttribute("data-theme");

// Alternate the theme (swap)
const newTheme = currentTheme === "dark" ? "light" : "dark";

// Set the new theme
document.documentElement.setAttribute("data-theme", newTheme);

// Force rerender which will make the TS code to read the CSS variable get the newest value
setCurrentTheme(newTheme);

Code Sandbox #2: Theme

Conclusion

It is reasonable to challenge the solution of using CSS as the source of truth for colors and styles. The argumentation of the lack of solid type and the possibility to miss typing the name is considerable. However, the opportunity to define the style in an agnostic way is valuable. CSS variables are usable in any old and new mechanism and are, in a way, future-proof. Also, it is framework agnostic allowing React or SolidJS, or Angular to consume the values. With the capability to change the value dynamically with CSS conditions, like with an attribute value change, the pattern works well for theming.