Posted on • Originally published atelian.codes on
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:
classElianCodesBg{staticgetinputProperties(){return['--color-for-bg'];}staticgetinputArguments(){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 aseliancodes-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.
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
.bg{--color-for-bg:lightgreen;background-image:paint(eliancodes-bg);}
depending on the element you set theclass="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 addstyle="background: linear-gradient(90deg, #FFF 50%, ${color.code} 50%)"
to the element in the case that thedark
(TailwindCSS darkmode) class wasn't there. This was the code before:
constsetBgColor=(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%)`)}elseif(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:
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:
<scriptsrc="https://unpkg.com/css-paint-polyfill"></script>
The use-color class
Theuse-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 theuse-color
class and add a tailwindtext-color-${color.class}
class, so that Tailwind would render it correctly.
To do this, I wrote some code:
constcolor=getNewColor();document.querySelectorAll('.use-color').forEach(element=>{colors.forEach(color=>element.classList.remove(`text-${color.class}`));element.classList.add(`text-${color.class}`)});
ThegetNewColor()
in above example would return a random color from an array with the tailwind class and color code as values.
constcolor={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);}
constcolor=getNewColor();document.documentElement.style.setProperty('--random-color',color.code)
This way a lot of code is replaced by way better lines!
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse