A code-efficient CSS pattern for your theming and coloring needs, inspired by OOP and CSS Variables

Adrian V
6 min readNov 11, 2020

--

Let’s talk about doing more with less code.

Do you struggle to write CSS classes to color and theme your components in a way that is easy to maintain and code-efficient ? That does not end up in hundreds of CSS classes ? Do your CSS libraries fail in simplicity, being lightweight, and code-efficient because of the hassle of managing all these colors ?

TLDR;

We propose a CSS pattern inspired by OOP that manages linear code-efficiency for theming and coloring in your web application. This substitutes to exponential code written in the style of generic libraries such as Bootstrap, Semantic, Tailwind.

We propose a lightweight library called Swatch ( https://swatch.dev ) that offer CSS classes and variables which expose this pattern in an efficient API. Swatch is pure-CSS, which means framework-agnostic. Also its source SCSS is easily customizable.

The problem : theming and coloring imply exponential CSS classes

We introduce you a pattern for writing CSS and modest library, called Swatch and based on that pattern, that aims at solving this issue. We’ve been using this pattern for over a year in production now. This pattern makes coloring and theming code-efficient.

What do I mean by code-efficient?

Probably, you have as many web devs used Bootstrap / Semantic / Tailwind / Material UI to build your UI. While we don’t criticize the fact these libraries are good to get started quickly, they soon become extremely cumbersome to use and maintain due to (1) the particular syntax of one CSS library (2) the huge amount of classes you need to know and write shall you want to extend a bit the core library features. In particular, for coloring, Bootstrap / Semantic / Tailwind have one class per color per component (.btn-red, .btn-green, .btn-orange, .btn-blue) … what if we could reduce it to just one class with a better pattern ?

Using these libraries, if you have 15 colors and want your buttons (.button), your cards (.cards) , and your labels (.labels) to be compatible with all of them, you would have

  • 15 Classes for the button (btn-red, btn-green) …
  • 15 classes for the cards (card-red, card-green) …
  • 15 classes for the labels

This 45 classes in total, and each of the classes has very little value expect passing a particular color to the element. (All the colors are consumed in the same way by the component).

And imagine how many classes we would have if we had 10 components or a complete 100-component library. This amount to an exponential way of coding CSS classes for coloring and theming… for each component you create, you need to create X classes of colors to it. (Of course, we would use a preprocessor SCSS/LESS mixin, but I am talking about the compiled CSS output and what gets executed in the browser). What if we could reduce it to just one CSS class compatible with all the colors simply by using a better pattern ?

That’s where our pattern and the Swatch library comes in.

Using the Setter/Getter pattern to achieve code-efficiency in theming and coloring

(Just a word of warning: although we find this new pattern very efficient, it is probably best suited for medium to advanced experienced developers).

We adapted a pattern that comes from Object-Oriented Programming, the Setter/Getter Pattern to CSS. If you’re unfamiliar with it, this article should give you an idea what the pattern is in Python.

The Setter/Getter pattern applied to CSS amounts to a three-step process. This is how it works.

1. We define CSS color variables at the:root level

Nothing extraordinary here, just the base CSS variable logic

:root {
--red: #f8333c;
--light-red: #f48489;
--dark-red: #df000a;
--on-red: #ffffff;
--orange: #f46036;
--light-orange: #f19d85;
--dark-orange: #dd3100;
--on-orange: #ffffff;
--yellow: #ffbf00;
--light-yellow: #f6ce55;
--dark-yellow: #b38600;
--on-yellow: #ffffff;
--olive: grey;
--light-olive: #a6a6a6;
--dark-olive: #635151;
--on-olive: #ffffff;
--green: #44af69;
--light-green: #7fc096;
--dark-green: #268045;
--on-green: #ffffff;
// .... And many other swatches
}

2. We use special CSS classes, called Setters, that take one of the root variables (for instance, — red) and translate it to a local variable (for instance — x).

We associate the previously defined root variables to a local variable, --x and its variants, --light-x, --dark-x, --on-x (on = contrast color).

.x-azure,
.xh-azure:focus,
.xh-azure:hover {
--x: var(--azure);
--light-x: var(--light-azure);
--dark-x: var(--dark-azure);
--on-x: var(--on-azure);
}
.x-blue,
.xh-blue:focus,
.xh-blue:hover {
--x: var(--blue);
--light-x: var(--light-blue);
--dark-x: var(--dark-blue);
--on-x: var(--on-blue);
}
.x-pink,
.xh-pink:focus,
.xh-pink:hover {
--x: var(--pink);
--light-x: var(--light-pink);
--dark-x: var(--dark-pink);
--on-x: var(--on-pink);
}

3. We “get” the local variables and apply it to our HTML

Now it’s time to consume this API ! We can for instance use some of the following getter classes (which are included in the Swatch library), or you can write your own.

.b-x {
background: var( --x);
}
.b-dark-x {
background: var( --dark-x):
}
.b-light-x {
background: var( --light-x);
}
.b-on-x {
background: var( --on-x);
}
.c-x {
color: var( --x);
}
.c-dark-x {
color: var( --dark-x);
}
.c-light-x {
color: var( --light-x);
}
.c-on-x {
color: var( --on-x);
}

Finally, your html will look like.

<div>
<div class='x-red xh-blue b-x'> This div has red background and blue on hover</div>
<div class='x-red b-x c-on-x'> This div has red background and contrasted text </div>
<div class='x-red b-light-x c-on-x'> This div has light red background and contrasted text </div>
<div class='x-red b-dark-x c-on-x'> This div has dark red background and contrasted text </div>
</div>

You can at the complete example and a live playground here : https://swatch.dev/docs/examples

In the end, what do we have ?

  • Root CSS variables, defined once and for all
  • One setter class per color, defined once and for all
  • One getter class per “use case”, this can also be understood as one class per component (example here).

You can implement this pattern yourself of simply use our llibrary, Swatch ( https://swatch.dev ) which will provide you with these three levels: you will get around 20 different colors with 4 shades each, you will get setter classes and getter classes.

The whole library is 15KB, and it boils down to 2.5KB gzipped. The best thing about it (in our opinion), is that this library is (S)CSS only. Subsequently it is completely framework-agnostic meaning you can use it with bare-bones HTML as well as your favorite front-end framework, think React, Angular, Vue, even Django, or WordPress.

Also, an example in production that uses this library site-wide.

We just finished writing the docs, and we would be really thankful for some adventurers to take a look at it, and tell us if our solution is usable and down-to-earth. If you like it, we would really value your feedback, either here, or as a Github issue.

Also, if you think our library is useful, please give us a star on Github, it would make us really happy!

Thanks for taking the time to read this and if you do, for considering this pattern in your applications !

Final words

Applying to Setter/Getter pattern to CSS allows for achieving theming and coloring on the component or application level with a linear quantity of compiled code. Thus, this represents a sizeable improvement over the old way of doing this (writing exponential CSS classes).

In consequence :

  • This allows for a HUGE reduction of CSS code relative to colors and theming (up to 90% when comparing component libraries made using this pattern with Bootstrap)
  • This pattern makes the CSS code much more maintainable.
  • Also, CSS vars make debugging in browser a breeze.

So far we are satisfied by the improvements that came from using this pattern in our projects, for over a year now. We would be glad to hear it helped you too. If you have any issues or suggestions about it please let us know here or at the github repository.

If you’re looking at the Swatch library, we’d like to make this clear : in our library, you won’t find any components or blocks. What we do is something simple: we just provide a simple implementation of the CSS pattern, we explained to take care of coloring and theming. Take a look at the docs or the examples to learn what you can build with it !

--

--