Raise your hand if you ever tried to create themes in a React, and found it pretty awkward to make it a provider? I can’t actually see your hands, so I’m gonna assume you did raise them.

Typically, and especially if you’re gonna use CSS in JS, you will stumble across a huge issue when trying to provide themes to your CSS powered app. Why? Mostly because your CSS won’t be as dynamic as your pretty JSX / ng-template. I’m not going to describe in depth the Context API in React, because it’s done in a very elegant manner here: https://reactjs.org/docs/context.html, and, surprise, the example used is, I give it to you: CSS Themes.

Now, not only this hugely inflate your components’ code, by suddenly making everything driven by Consumer components, but it also makes it very opinionated, and might even affect performances. Solution? Well here’s another take on this: ElectronCSS now propose a DynamicCSS API to solve that issue.

Getting Started

If you haven’t already, you should start with ElectronCSS’ Getting Started article, in order to set up your environment. Once again, if you’re too lazy, you can follow with this JSFiddle:

How to use it

The first step into creating a dynamic set of properties is to set up an object your classes can subscribe to.

const Theme = DynamicCSS();

By convention, this object is given a PascalCase name. You can also provide default values for the properties :

const Theme = DynamicCSS({

mainColor: color.red

});

Now that we have our theme, let’s use it in our CSS :

const Theme = DynamicCSS({

mainColor: color.red

}); const myButton = CSS({

backgroundColor: Theme.mainColor

});

You have probably noticed that DynamicCSS objects are not restricted to actual CSS properties, you can put anything you need in there. You usually want to refactor your color codes the way a designer would do it with his/her own palette of colors, so you can re-use them everywhere.

Finally, obviously, you will want to use your CSS class somewhere :

const Theme = DynamicCSS({

mainColor: color.red

}); const myButton = CSS({

backgroundColor: Theme.mainColor

}); <div class={myButton}></div>

Now what? Well, this is where the magic strikes in. Say your user want to switch your website to night mode. All you have to do is to create a plain object with the properties matching your night mode and use it using Theme.use(). here is a working example:

By the way, I’ve been talking a lot about themes, but don’t let that stop you: DynamicCSS have a lot of other uses, for example reacting to the user actions, like scrolling and mouse movements.

Use and Inject

You have two ways of updating your dynamic css properties. The first version, use(), as we saw before, will reset your CSS entirely.

const Theme = DynamicCSS();

Theme.use({

color: 'red',

width: '1px'

}) Theme.use({color: 'blue'}); // here the width will be removed from the theme

This is very useful most of the time when you want to load a global theme/layout for your website and you worry old properties might mess up the result because the newly selected theme doesn’t actually overwrite them.

In some circumstance, you might want to load the theme for a more local edit.

const Theme = DynamicCSS();

Theme.use({

color: 'red',

width: '1px'

}) Theme.inject({someThirdPartyProperty: '123px'}); // here the width and color will remain the same

This is very useful in case you have a more modular approach with sub-themes for particular components (or 3rd party’s). But don’t abuse it as it may result in unexpected result (nothing is reset !).

How it works

In this article, I chose to go more into details with the technical background noise. If you’re not interested in this part, skip ahead to the conclusion!

The rules

Whenever a DynamicCSS is created, you basically create an observable object. It actually does have a subscribe() function !

const test = DynamicCSS(); // foo is a classname for who is subscribing

test.subscribe('foo', () => {

console.log('ho ! ho !');

}); test.refresh(); // ho ! ho !

There is a major difference though: every time the subscribers are notified, they will be unsubscribed! Continue reading to understand why.

The classes

Every time you try to refresh a CSS object in Electron, it *won’t* try to edit it directly in the stylesheet : that would be too much work, as you usually have multiple rulesets for the same class (pseudo-elements like :hover, containments, media-queries, etc…) and filtering all potential candidate would require going through the whole stylesheet. Instead, ElectronCSS is going to simply swap the classname of your element :

const test = DynamicCSS({

foo: 'bar'

}); const testCSS = CSS({

color: test.foo

}); console.log(testCSS.toString()) // .class0 test.use({foo: 'notbar'}); console.log(testCSS.toString()) // .class1

it *will* manipulate your DOM to apply this new class. Upon rendering, this new class will then subscribe to your DynamicCSS rules accordingly to their definition.

What happens to the old classes? They simply get removed by ElectronCSS’ internal garbage collector!