Add themes to Angular using CSS variables
Providing different themes for users to choose from has become pretty much a standard these days and it’s quite easy to implement using Angular. In this article, we are going to learn how to add themes to Angular apps using a simple service and the power of CSS variables (aka CSS custom properties).
Here is what we are aiming for
- Multiple themes to choose from (light, dark, and possibly more)
- Store the selected theme in local storage
- Apply stored theme upon revisit
And here is what the final result looks like,
Overview
We are going to create a service to hold the “active theme” as a state and also it will be responsible for changing the theme. This is going to be achieved by swapping CSS classes associated with the theme. CSS classes in return will be responsible for the theme change via CSS variables.
Define Themes
Let’s jump right into it by defining the themes we want to have in the application. To do so, we are going to create a file called theme.ts
and expose an object from it. Keys of the object will be the theme names and their values will be the CSS classes associated with the theme. Here is an example in which we defined light, dimmed, and dark themes:
Theme Classes
In the next step, we are going to create CSS classes. Navigate to your global stylesheet (styles.{scss,css,less}
) and add the following code to it.
You can add more variables if you need to. Notice that I already used two of the CSS variables in the body
element. Right now, it doesn’t do anything because we haven’t set the theme just yet.
Theme Service
Now that we defined our themes and created CSS classes, we are going to create a service to hold the active state and change it. Create a service called theme
and add the following code to it.
There are a couple of things to mention here.
BehaviorSubject
is used to keep the active theme as a state.activeTheme
getter method is created to get the active theme. An observable alternative,activeTheme$
, is also added in case we want to subscribe to it.- To set the theme,
set(...)
method is created which takes “theme name” as an argument. Using the themes we defined earlier intheme.ts
, it will remove and add CSS classes to thedocumentElement
. - Also, I’ll throw in a getter method called
themeNames
to list all the possible themes.
Usage
To use the service, inject it into the app component and call the set(...)
method.
And that’s it, theme selection is working. This will set the ‘light’ theme by default. You can add more styles for the component and start using themes in the application.
This is nice and all but regardless of what the user selects, the selection will be lost on a page reload since it’s not saved anywhere. Let’s fix this problem by adding local storage to the implementation.
With Local Storage
We’ll change some code in the app component.
- Check local storage first to see if a value is set.
- If there is a value, and the saved value is listed in the
theme.ts
we created earlier, set the theme. If not, set the ‘light’ theme as the default theme. - Start listening to the theme changes using
activeTheme$
observable and set the new theme to the local storage.
Here is the new implementation of app component,
And with these small changes, the selected theme will be set when you reload the page or revisit it later on.
Bonus: Use it with Tailwind CSS
The same service can be used to toggle light and dark modes in Tailwind CSS. You can refactor it in two ways:
- Either change
theme.ts
and remove “-theme” suffix from themes. And don’t forget to remove them from the classes instyles.{scss,css,less}
as well. And finally, add the following line to yourtailwind.config.js
file.
module.exports = {
// ...
darkMode: 'class'
}
2. Second way is to keep everything as is and just add the following to tailwind.config.js
module.exports = {
// ...
darkMode: ['class', '.dark-theme']
}
Done! 🎉
And that’s really it!
You can find more utilities like this in the following repo 🙌