It is becoming more and more popular to add a dark-theme to an application. Night owls also need some comfort of reading! It also enables people with sight problems to have a chance to comfortably read websites without a magnifying glass with the help of high-contrast colours. Every day new software companies add theme switching to their products, being aware of multiple of accessibility and comfort values it brings.
And so do we at FIS-SST!
As frontend developers, we often use some UI library like Angular Material which enables theme-switching out of the box. Things get a little bit more complex when the frontend team needs to implement such a functionality on their own. Is there even a good way to approach this problem? Let’s analyse the below solution and find out.
The below examples use Angular with SCSS, but the idea behind this structure and workflow is universal and might be used in any front-end technology.
- Single source of colours provided by UI team
- Implementing smooth changes after UI team updates
- Provide readability and ease of adaptation for new devs
- Make it possible to toggle themes during run-time
Below I will walk you through several steps showing a simplified procedure for adding high-contrast mode and dynamically switch it in our project
Step 1: UI team – developers interface
With large projects, where each team (UI, frontend, backend, dev-ops) is concerned with their own duties, communication is essential for delivering products on time. In this case, let’s have a closer look at UI – Frontend cooperation and data transfer.
Having values of colours defined by the UI team, it is time to keep them somewhere in the code. Let’s create a file called variables.scss, inside of which we will have the following content:
As of this point, any change of colours by the UI team will only need to be reflected in this place.
** Please note, that I define white and black colours as both main and contrast variable. This is to prevent future change of black to e.g. dark-grey only for contrast theme.
Step 2: Dynamically create css classes for each theme
At first we need to define a css variable for each colour, containing value for both light and contrast themes. In parentheses, the first value is intended to be used in light theme, the latter one in contrast theme.
** Css variables are variables containing some css value, being accessible globally. For more information you can read: https://developer.mozilla.org/en-US/docs/Web/CSS
In Angular, we usually have style.scss autogenerated for us by Angular CLI. In that file, we first import our variables.scss and then themes.scss, where we created regular css classes, however, not by hand, but implicitly with the help of dynamic SCSS features.
Let’s analyse line by line what is going on there, as logical operations as this one are not something you’ll see every day whilst styling.
Line 4: Creation of regular css class
Line 5: Iteration through $variables, which we imported from variables.scss
Line 6: Creating css variable, for example: —main-color-green: #56e13d;
The same process is repeated for .theme-contrast class, only the other value is taken.
Step 3: Toggle classes
Now, having necessary css classes holding values for both themes, we need to toggle them, depending on our needs.
That can be quite easily achieved with the following lines of code:
Depending on your code structure, this could be held in a service or directly in a component.
** Code snippet above shows a general approach to attaching and detaching classes as it comes from Web API. If you use Angular, it is recommended to use Renderer2 for these operations.
** Hint: It is also advisable to make theme switching session-independent. One can achieve that by keeping current theme value in LocalStorage.
Step 4: Using css variables in the code
Now that all set-up steps have been completed, we can start using our global variables in the code. Let’s take styling a button as an example.
As you see, in order to consume a css variable, it needs to be explicitly placed inside var() as an argument.
Step 5: Use :host-context for more advanced cases
When speaking about changing themes of your front-end application, it is also crucial to be aware of :host-context(), provided by angular. In step 3 we attached our “theme-contrast” class to document’s body, which is the highest possible element a css class can be attached to. Having that in mind, we can refer to it from any .css or .scss file across the application. Check the example below:
** Please note, that both .theme-light and .theme-contrast can be attached at the same time. That’s why when switching, we need to detach one class and attach the other.
When adding theme-switching in custom-styled application, there are a couple of steps we need to take care of. However, when applied correctly, we get easily maintainable and scalable solution. This approach is almost not vulnerable to issues with design changes as all data (colours, borders, widths, heights etc.) provided by UI team is sitting in one place instead of being scattered across the entire application.
- Great article about :host-context and not only by Vasco from Angular University:
- Official Angular info about :host-context: