Angular 6: Dynamic Themes Without a Library
Tags: angular, theme, native
Published: 2018-06-02 20:41:28

---
title: Angular 6: Dynamic Themes Without a Library
published: true
description: 
tags: angular, theme, native
---

The concept of theming has been around as long as I can remember. Giving users the ability to choose the look and feel of your product has incredible value — it creates a more localized experience and reduces developer maintenance time.

![tumblr](https://cdn-images-1.medium.com/max/1600/1*Eb0kS7HGmxFyZR2HokgNhQ.png)

How can we create something like this in our Angular apps?

##Why Sass Alone Won’t Work

Although Sass variables may work to create a preset themed experience, the biggest drawback is that it can’t be manipulated by JavaScript. We need JavaScript to dynamically change the value of our variable!

## Why Material Alone Won’t Work

Ever since Angular Material was released, developers have been flocking to this library to utilize their reusable components (not to mention built-in accessibility)

Material comes with built-in theming, but this may not work for two reasons:

1. By default, Material comes with it’s own color palette that is optimized for accessibility. If you want to generate more colors, you’ll need to pass it into their mat-palette mixin or create a new theme file, using 3rd party tooling. This creates an external dependency and restricts the ability to switch themes without touching code.

2. Although it is a great option, not everyone wants to use Material! Many developers do not wish to import an entire library to utilize components and opt to create their own.

**The solution? Sass + CSS Variables!**

If you have never used native CSS Custom Properties (I call them variables), there is a great article (here) to help you get started. The reason this approach works is because CSS variables can manipulated by JavaScript! With this combination, you can use a form to pass CSS variables to a Sass map, which can be used throughout the app.

## Let’s See It!

![implementation](https://cdn-images-1.medium.com/max/1600/1*XAFHjvjzDS1ZIaroeHKIpQ.gif)

**This implementation:**

- Does not use any external libraries
- Allows multiple components to dynamically change styles through a form
- Saves the form as an object that can be saved in a database or local store
- Has the capability to load an external object as a preloaded or preset style

Link to Demo: https://native-theming-form-medium.stackblitz.io/

Link to Stackblitz: https://stackblitz.com/edit/native-theming-form-medium

## The Magic

The core principle behind this method is combining Sass maps and CSS Variables.

In thetheme.scss file, the default values are set and passed into a Sass map

theme.scss
```
// default colors
.theme-wrapper {
    --cardColor: #CCC;
    --cardBackground: #FFF;
    --buttonColor: #FFF;
    --buttonBackground: #FFF;
    --navColor: #FFF;
    --navBackground: #FFF;
    --footerColor: #FFF;
    --footerBackground: #FFF;
    --footerAlignment: left;
}
// pass variables into a sass map
$variables: (
    --cardColor: var(--cardColor),
    --cardBackground: var(--cardBackground),
    --buttonColor: var(--buttonColor),
    --buttonBackground: var(--buttonBackground),
    --navColor: var(--navColor),
    --navBackground: var(--navBackground),
    --footerColor: var(--footerColor),
    --footerBackground: var(--footerBackground),
    --footerAlignment: var(--footerAlignment)
);
```

A function is created to return the native css variable from the global sass map

function.scss

```
@function var($variable) {
    @return map-get($variables, $variable);
}
```

The components can now read these two files to host a dynamic variable that changes upon form resubmit

card.component.scss

```
@import '../../theme';
@import '../../functions';
.card {
    background-color: var(--cardBackground);
    color: var(--cardColor);
}
```

The card’s background color is now #FFFFFF and text color is #CCCCCC

But how do we change the values?

Through the theme-picker component!

In our theme-picker.component.html file, we are using template forms with ngModel to create an object with a unique key (style) and value (input). The object then gets passed to the TypeScript file which dynamically overwrites the variable.

theme-picker.component.ts

```
// searching the entire page for css variables
private themeWrapper = document.querySelector('body');
onSubmit(form) {
    this.globalOverride(form.value);
}
globalOverride(stylesheet) {
    if (stylesheet.globalNavColor) {
        this.themeWrapper.style.setProperty('--navColor',     stylesheet.globalNavColor);
    }
...
    if (stylesheet.globalButtonColor) {
        this.themeWrapper.style.setProperty('--buttonColor',     stylesheet.globalButtonColor);
    }
}
```

The globalOverride function checks to see if a value exists for that specific variable, then replaces each CSS Variable with the new inputted one.

**Violá!**

This code can be better optimized to scale (using preset style objects, saving/publishing styles on submit), so feel free to play around with it!