Write less code by using CSS Houdini
Tags: css, javascript, houdini, webdev
Published: 2021-10-15 13:19:59

---
title: Write less code by using CSS Houdini
published: true
date: 13/10/2021
tags: CSS, Javascript, Houdini, Webdevelopment
canonical_url: https://www.elian.codes/blog/10-13-21-adding-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:

```javascript
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:

```css
background-image: paint(eliancodes-bg);
```

That's basically it!

[The package is available on NPM](<https://www.npmjs.com/package/eliancodes-bg>), 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.

```javascript
CSS.paintWorklet.addModule('https://unpkg.com/eliancodes-bg@0.0.1/index.js')
```

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

```css
.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:

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

after upgrading to houdini, it got replaced by:

```typescript
document.documentElement.style.setProperty('--color-for-bg', 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:

```javascript
<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:

```typescript
const color = getNewColor();
document.querySelectorAll('.use-color').forEach(element => {
    colors.forEach(color => element.classList.remove(`text-${color.class}`));
    element.classList.add(`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.

```js
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:

```css
:root {
    --random-color: lightgreen;
}

.use-color {
    color: var(--random-color);
}
```

```typescript
const color = getNewColor();
document.documentElement.style.setProperty('--random-color', color.code)
```

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