← Back to blog

Published on 10/13/2021 19:10 by Elian Van Cutsem

Write less code by using CSS Houdini

Some time ago I started looking into CSS Houdini. It was awesome already, you could do a lot of cool things with it, but I didn’t really see a use of the available things at the time. Today was the day that I looked back at CSS Houdini and refactored some of my code to use CSS Houdini.

Writing the package

The thing I wanted to create in Houdini is my background gradient. This isn’t hard to do in CSS or anything, but 1. it was a good practice to learn CSS Houdini 2. required less code 3. now supports CSS custom properties out of the box.

Writing a package for Houdini isn’t that hard (at least, this was a simple one, I imagine some are way harder).

You start by defining what your package should do:

class ElianCodesBg {
  static get inputProperties() {
    return ["--color-for-bg"];
  static get inputArguments() {
    return ["<color>"];

  paint(ctx, size, props) {
    ctx.fillStyle = props.get("--color-for-bg");
    ctx.fillRect(size.width / 2, 0, size.width, size.height);
registerPaint("eliancodes-bg", ElianCodesBg);

here we defined that the Worklet should use one input property called --color-for-bg, which is a color type. Next we define that it should draw a rectangle with half of the width of the element and the same height.

At last, the Paint get registered as eliancodes-bg so you can use that in your CSS like:

background-image: paint(eliancodes-bg);

That’s basically it!

The package is available on NPM, although it should be fine to load it over CDN.

Using the package

add this code to your html as a <script> or add it in an already linked JS-file.


using that javascript, we could just set a custom color in the CSS file

.bg {
  --color-for-bg: lightgreen;
  background-image: paint(eliancodes-bg);

depending on the element you set the class="bg" on, half of the background will be filled with the --color-for-bg color.

Check the codepen here: https://codepen.io/elianvancutsem/pen/wvqaXQV

Refactoring the old code

Now that the package was published I only needed to rewrite some of my older Astro & TypeScript code to use regular CSS and Houdini instead of a lot of TypeScript code.

The index background

If you look at my website, one of the first things people notice, is that the background on the homepage has a 50% white, 50% random color gradient. Prevously, the background was generated by a lot of shitty TypeScript code that looked at the class in the <html> element and would add style="background: linear-gradient(90deg, #FFF 50%, ${color.code} 50%)" to the element in the case that the dark (TailwindCSS darkmode) class wasn’t there. This was the code before:

const setBgColor = (color) => {
  if (
    document.querySelector("html").getAttribute("class") != undefined &&
    !document.querySelector("html").getAttribute("class").includes("dark") &&
  ) {
        `background: linear-gradient(90deg, #FFF 50%, ${color.code} 50%)`,
  } else if (
  ) {
        `background: linear-gradient(90deg, #000 50%, #000 50%)`,
  } else {
    document.querySelector("html").setAttribute("style", "");

after upgrading to houdini, it got replaced by:

  document.documentElement.classList.contains("dark") ? "black" : color.code,

The --color-for-bg custom property gets used by the Houdini package and will make the background work without any other code!

Adding a polyfill

One of the things you notice when playing around with CSS Houdini, is that it’s not supported (yet) in all browsers. The Paint API already shipped in chrome, but is still under review in Firefox for example. Luckilly, the guys at Houdini created a polyfill that will make it work with all browsers and it’s very easy to add.

Just add this line in your body to use the polyfill on not-supported browsers:

<script src="https://unpkg.com/css-paint-polyfill"></script>

The use-color class

The use-color class is the class I custom set to change the textcolor of different elements to the active accent-color. Also this got extremely refactored! Before I would manually find all elements with the use-color class and add a tailwind text-color-${color.class} class, so that Tailwind would render it correctly.

To do this, I wrote some code:

const color = getNewColor();
document.querySelectorAll(".use-color").forEach((element) => {
  colors.forEach((color) => element.classList.remove(`text-${color.class}`));

The getNewColor() in above example would return a random color from an array with the tailwind class and color code as values.

const color = { class: "primary-green", code: "#86EFAC" };

This got refactored to a very simple method where a CSS custom property would get changed from TypeScript:

:root {
  --random-color: lightgreen;

.use-color {
  color: var(--random-color);
const color = getNewColor();
document.documentElement.style.setProperty("--random-color", color.code);

This way a lot of code is replaced by way better lines!

Written by Elian Van Cutsem

← Back to blog
  • So, I'm leaving vBridge

    So, I'm leaving vBridge

    After spending a couple of years at vBridge Cloud, I'm leaving the company. I've worked at vBridge eversince I graduated. Now, It's time for a new adventure! I'm joining the DX-team at Astro full-time!

  • Becoming an Astro maintainer

    Becoming an Astro maintainer

    Since a week, I'm an Astro maintainer, in this post, I describe the process and my start in open source. I also give some insight in what I'm planning to work on.

  • 🍱 Brutal: A theme for Astro

    🍱 Brutal: A theme for Astro

    Brutal is a minimal neobrutalist theme for Astro. It's based on Neobrutalist Web Design, a movement that aims to create websites with a minimalistic and functional design. It has some integrations like Image Optimization, RSS, Sitemap, ready to get your SEO done right.

  • 🎤 Am I an international public speaker now?

    🎤 Am I an international public speaker now?

    A few weeks ago, I gave my first international keynote talk at JSWorld in Amsterdam. In this blogpost, I wanted to share some insights about the conference and my talk.

  • ✨ Building Blog tag index pages in Astro

    ✨ Building Blog tag index pages in Astro

    I wanted to add blog tag collection pages to my website. This way, people could filter on tags I used in my blog posts. Here is a guide on how I implemented it.

  • 🎉 I started from scratch (again)

    🎉 I started from scratch (again)

    I started rebuilding my personal website from scratch in Astro again, no dependencies, no frameworks, no nothing. This to decrease technical debt and make full use of the newer Astro features.