Dynamic Brand theming using CSS variables 
Tags: javascript, css, design, html
Published: 2021-06-26 14:38:03

Recently, I got to work on an e-commerce checkout page builder (No code tool) where the merchants can change the theme according to their brand. The merchants can configure their brand colour and secondary colour to various elements like buttons, containers, texts, etc. This configuration will be fetched using APIs and applied to checkout pages on rendering. I was exploring various approaches such as **SASS/LESS/Stylus variables, CSS-in-JS libraries and CSS variables** for applying the theme. After a deep exploration, I ended up using CSS variables. In this article, I would like to explain the pros and cons of each approach and how I ended up using CSS variables.

##SASS/LESS/Stylus variables:
CSS preprocessors are scripting languages that allow developers to write DRY styles using variables, functions, mixins, etc. These DRY styles would be converted into raw CSS styles in compile time. If we are aware of all theme-related information during compile time, we can easily map them to these variables and achieve theming. As the checkout has to allow the merchants to change the theme dynamically in run time, we cannot go with this approach.

##CSS-in-JS libraries:
There are many CSS-in-Js libraries available in the market such as **styled-components, emotion, glamorous,** etc. These provide extensive theming support. However, these libraries require `<ThemeProvider />` which has to be wrapped over the app in order to provide theming context. Vendor lock-in is another disadvantage of using this. We will not be able to easily switch to a different approach in the future. As we got used to the traditional CSS approach, the learning curve is also steep.

## CSS Variables:
CSS variables a.k.a custom properties allow us to change the values dynamically in the run time using Javascript. We can use var()to use a variable in the references of the stylesheet. You can assign the value of CSS variable either in CSS or javascript. Many latest browser versions support CSS variables. As CSS variables are supported by native CSS and the learning curve is also shallow, I preferred CSS variables for my theme-able system.

Let’s create a simple checkout page that contains the shipping address section, the payment section and the cart section. The merchant would be able to configure `brandColor`, `secondaryColor` and `bodyBackgroundColor` for these sections.

![Checkout mockup image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lfxl9lf9npz19hexa69i.png)

###Step 1 — Mapping the variables to check out elements
Let’s map each variable to the respective checkout elements.
**brandColor**- This is used for primary buttons, logo and border colours
**secondaryColor** — This is used in the apply coupon input group
**bodyBackgroundColor**- This is applied as a background colour to the main container.
![Checkout mock ip image with pointers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/doyl43z973yvewb5zlx9.png)


###Step 2 — Using the CSS variables in the stylesheet.
To assign a CSS variable to a property, we have to use `var()`.

Let’s have a look at the selectors which use `brandColorvariable`. The value for this variable will be set using javascript during run time.
{% gist https://gist.github.com/mathumi/a5f13cae05ab9a910c28f03c35862e31 %}

`secondaryColor` variable is used for the apply coupon button.
{% gist https://gist.github.com/mathumi/9061fbcdebbfb17cec84217e27f7495f %}

`bodyBackgroundColor` is applied to the main container of the application.
{% gist https://gist.github.com/mathumi/c7c1730547c43795b1cf68e231842d01 %}

###Step 3 — Creating Merchant configuration JSON
Our theme builder configuration will be exposed via API from the server. The configuration JSON will be looking something like this
{% gist https://gist.github.com/mathumi/ec19307d58c44fc663e11fe583487750 %}

In order to demo, let’s mock the server response with static JSON. `getMerchantConfigfunction` will return a promise which resolves the merchant configuration using the `merchantId` argument.
{% gist https://gist.github.com/mathumi/818d6a0f912f0aab9345d9a8f2d7ffcf %}

###Step 4 — Setting values for CSS variables in Javascript
Now, let’s see how the variables are set in Javascript. As the variables are used across the stylesheet, let’s set the variables in the root element.

```javascript
const root = document.querySelector(':root');
root.style.setProperty('--brandColor', merchant.brandColor);
root.style.setProperty('--secondaryColor', merchant.secondaryColor);
root.style.setProperty('--bodyBackgroundColor', merchant.bodyBackgroundColor);
```
Now, we have to get the theme configuration for the merchant. Let’s say Merchant 1 is active. we have to call `getMerchantConfig` function by passing merchantId `merchant1`.
```javascript
const setTheme = async () => {
  const merchant = await getMerchantConfig('merchant1');
  const root = document.querySelector(':root');
  root.style.setProperty('--brandColor', merchant.brandColor);
  root.style.setProperty('--secondaryColor',     merchant.secondaryColor);
  root.style.setProperty('--bodyBackgroundColor', merchant.bodyBackgroundColor);
};
setTheme();
```
The final Js code will be looking like this.

{% gist https://gist.github.com/mathumi/c1c76ae0b6b67a975bcea4a0cd7d51af %}

That’s all, We are done with it 😎. You can see the working demo in the codepen. You can play around by passing different merchantIds to getMerchantConfig function. You can also try configuring other properties such as font-size, font-family, etc.

{%codepen https://codepen.io/mathumithapalani/pen/OJpBGjL %}


##Conclusion:
Theming is much more simplified using CSS variables. There is no vendor lock-in. CSS variables are supported by native CSS and have great browser compatibility. It’s the best fit for my feature. CSS variables have much more potential other than theming. It reduces plenty of repetitive tasks. You can give it a try. I’m attaching a few good resources here.

1. https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties#basic_usage
2. https://electerious.medium.com/the-power-of-css-variables-6c4e4ebaf279