DEV Community

Cover image for Don't make your users suffer without dark mode! CSS variables are here to help
Oleg Proskurin
Oleg Proskurin

Posted on • Edited on

Don't make your users suffer without dark mode! CSS variables are here to help

In the present day, a desired feature is the capability to create themes for applications and websites. Users now anticipate being able to personalize the look of the applications they use and offering options for themes including dark themes has become crucial for enhancing user experience and accessibility. In this article, we will delve into implementing theming in your applications using CSS variables. This approach empowers you to offer an adaptable experience, for your users.

Understanding CSS Variables

Before we dive into the specifics of implementing theming, let's first take a moment to understand what CSS variables are and how they work. CSS variables, also known as custom properties, allow us to define reusable values throughout our CSS files. They are defined using the -- prefix and can be accessed using the var() function. For example, to define a CSS variable for the primary color of your application, you can use the following syntax:

:root {
  --primary-color: #ff0000;
}
Enter fullscreen mode Exit fullscreen mode

Once defined, you can use the variable in your CSS rules by referencing it with the var() function, like this:

.button {
  background-color: var(--primary-color);
}
Enter fullscreen mode Exit fullscreen mode

CSS variables provide a powerful way to centralize and reuse values in your CSS, making it easier to maintain and update your styles.

Implementing Theming in your App

Now that we have a basic understanding of CSS variables, let's see how we can utilize them to implement theming in a website or application. There are several approaches to achieving theming with modern CSS frameworks, but in this article, we will focus on a simple and effective method using CSS variables. If you are still more interested in how to deal with themes in Tailwind CSS please check this my article.

Step 1: Define Your Theme Variables

The first step is to define the variables for your themes. You can do this by creating a separate CSS file or by utilizing a CSS-in-JS solution like styled-components. For example, let's define the variables for a light and a dark theme:

:root {
  --primary-color: #ff0000;
  --background-color: #ffffff;
  --text-color: #000000;
}

[data-theme="dark"] {
  --primary-color: #00ff00;
  --background-color: #111111;
  --text-color: #ffffff;
}
Enter fullscreen mode Exit fullscreen mode

In this example, we have defined variables for the primary color, background color, and text color for both the light and dark themes. By using the :root selector, we ensure that these variables are available throughout our application.

Step 2: Implement Theme Switching

Next, we need to implement the logic for switching between themes. One common approach is to use a button or a toggle switch that allows the user to switch between the available themes. We will show the logic on an example of the React app, but you can implement a similar switcher even if you don't use any frontend framework. When the user interacts with this element, we can toggle a data-theme attribute on the root element of our application, which will trigger the corresponding CSS rules.

import React, { useState } from "react";

const App = () => {
  const [theme, setTheme] = useState("light");

  const toggleTheme = () => {
    setTheme(theme === "light" ? "dark" : "light");
  };

  return (
    <div data-theme={theme}>
      <h1>Welcome to My App</h1>
      <button onClick={toggleTheme}>Toggle Theme</button>
    </div>
  );
};


export default App;
Enter fullscreen mode Exit fullscreen mode

In this example, we use the useState hook to manage the current theme state. When the toggle button is clicked, the toggleTheme function is called, which updates the theme state accordingly. The data-theme attribute is then set on the root div element, which triggers the appropriate CSS rules.

Step 3: Apply Theme Variables in Your CSS

Now that we have the theme switching functionality in place, we can apply the theme variables in our CSS rules. By utilizing the CSS variables we defined earlier, we can easily update the appearance of our components based on the selected theme. Here's an example:

.button {
  background-color: var(--primary-color);
  color: var(--text-color);
}

body {
  background-color: var(--background-color);
}
Enter fullscreen mode Exit fullscreen mode

In this example, we apply the theme variables to the background color and text color of the body element, as well as the background color and text color of the .button class. By referencing the variables with the var() function, the styles will automatically update when the theme changes.

Additional Possibilities with CSS Variables

CSS variables not only enable theming in your applications but also unlock a range of other possibilities. Let's explore some of these possibilities:

Animate Any Property

With CSS variables, you can animate any property, even those that traditionally cannot be animated. By applying transitions to the values of CSS variables instead of the properties themselves, you can create smooth and dynamic animations. For example, you can animate the background color of an element using CSS variables:

@keyframes color-transition {
  from {
    --background-color: red;
  }
  to {
    --background-color: blue;
  }
}

.element {
  background-color: var(--background-color);
  animation: color-transition 1s infinite alternate;
}
Enter fullscreen mode Exit fullscreen mode

In this example, we define a keyframe animation that transitions the --background-color variable from red to blue. We then apply this animation to an element, resulting in a continuous color transition effect.

"Dark Mode" Flash Fix

Implementing a "Dark mode" variant in your application can sometimes lead to a flash of incorrect colors during initial page load. This happens because the HTML is generated before the user's preferred color scheme is known. However, with CSS variables, you can solve this issue by defining a default value for the variables and updating them dynamically based on the user's preference.

:root {
  --background-color: #ffffff;
}

@media (prefers-color-scheme: dark) {
  :root {
    --background-color: #000000;
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example, we define a default background color for the --background-color variable. We then use a media query to detect the user's preferred color scheme and update the variable accordingly. This ensures that the correct color scheme is applied from the moment the page loads, eliminating the flash of incorrect colors.

Conclusion

In conclusion, CSS variables provide a powerful and flexible way to implement theming in your applications. By defining reusable variables and dynamically updating their values, you can create customizable and visually appealing experiences for your users. Additionally, CSS variables unlock new possibilities such as animating any property and solving issues like the "Dark mode" flash. So why not leverage the power of CSS variables in your next project and take your application theming to the next level?

Remember, as a developer, mastering CSS is essential regardless of whether you choose to use CSS-in-JS or traditional CSS. CSS variables are just one tool in your toolkit, and understanding how to use them effectively will make you a more effective front-end developer.

So go ahead, embrace CSS variables, and create beautiful, themable applications that will delight your users. Happy theming!

Top comments (0)