DEV Community

Cover image for Themify your app with Custom Properties
Benjamin Petetot
Benjamin Petetot

Posted on • Updated on • Originally published at petetot.netlify.com

Themify your app with Custom Properties

My current side-project is an open SaaS platform to manage call for papers called Conference Hall. When I started it, I wanted to have different themes following the user's role. A blue theme if you are a speaker, and a red one for organizers.

The application is currently built with React and there are plenty of ways to build a theming system using providers, hooks, styled components, css-in-js etc. But I wanted to keep it simple and closed to what it's supposed to be: "style". So I decided to use one of the new powers of CSS: "Custom Properties" (or CSS variables) and its inheritance system.

Here a live demo and explanations following.

Themify with custom properties

First declare a default theme with all custom properties needed for the theme.

.default-theme {
  --background-color: #FFF;
  --font-color: #000;
}
Enter fullscreen mode Exit fullscreen mode

Set the default theme class to the body (or an other root element). This element and its children will have access to the variables.

<body class="default-theme">
...
</body>
Enter fullscreen mode Exit fullscreen mode

These variables can be used in your CSS through the var() function.

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

So, what should we do to change the theme of the app ?

Declare a new CSS class with the custom properties to override in the new theme, then apply it to the element. Thanks to the inheritance of custom properties you have the dark mode in your application.

.dark-theme {
  --background-color: #000;
  --font-color: #FFF;
}
Enter fullscreen mode Exit fullscreen mode
<body class="default-theme dark-theme">
...
</body>
Enter fullscreen mode Exit fullscreen mode

Apply theme to sub-components

If you use the custom properties (var()) in all your sub-compoments the theme will be automatically applied.

But you may build your components independently from your application (with Storybook, DocZ, etc.) and the theming system implies that some of your components should use these custom properties. So if you want to have a component that renders correctly without declaring CSS variable, you can:

  • Pass the CSS variable through a color props to the component;
  • Pass class or style with CSS variables to the component;
  • Or use the CSS variable inside of it with a fallback value (2nd parameter of the var function):
.my-component {
  background: var(--background-color, #DDD), 
}
Enter fullscreen mode Exit fullscreen mode

Browser compatibility

Most browsers already support custom properties except Internet Explorer. But if you want to keep a fallback for IE you can add an additional property in the CSS class. Of course, theme switching will not work on IE with custom properties.

.my-component {
  background: #DDD, 
  background: var(--background-color, #DDD), 
}
Enter fullscreen mode Exit fullscreen mode

All the theming system of my application Conference Hall is entirely based on custom properties and works very well. I hope it will help you.

See the live demo in codepen:

Top comments (1)

Collapse
 
ctrl_alt_aldr profile image
Christian | πŸ§‘πŸΌβ€πŸ’»

Nice! CSS Variables seems perfect for handling themes, I will be sure to adopt it soon for a project of mine that I wanted a light/dark mode for :)
Thanks for sharing your method