Adventures in theming
Posted by Jonny on
Using products like Twitter and Trello every day, I've long appreciated the importance of making my regular online tools feel like home. Luckily since Progression's inception we've allowed teams to enter a hex value as their brand colour. We just never really used them (which thinking about it must have been pretty underwhelming).
Well this week I did one of my classic 'not on the roadmap' evening hacks, and decided to spend an hour or two seeing how hard it would be to add theming into our app.
It would turn out to be an interesting journey of discovery with a lot of 'today I learned' moments.
Not all colour spaces are created equal.
Everyone understands HEX (i.e. #ff0000). And in fact most understand RGB too – three numbers from 0-255 corresponding to Red Green and Blue. HSL is the lesser known cousin, but by far the most powerful of the colour spaces.
HSL stands for Hue, Saturation and Lightness. Hue is measured as a 360° colour wheel and saturation and lightness are 0-100%. What's great though is that having lightness and saturation allow you to manipulate a colour programatically in a really easy way without affecting the important one for most, the hue. And Hue being seperate means you can programattically find complimentary colours by just subtracting an 'angle' from your hue value.
So, a worked example. If I have an HSL colour of
145°,44%,81% I can decide to spit out complimentary colours by changing the Hue, shades of the same colour using the lightness and I can also avoid some of the crazy combinations that make UI unusable by controlling saturation. All just with maths. 🤯
I didn't know that when asking people for a HEX code as their brand colour, but to be fair asking for an HSL would have resulted in mainly confusion anyway. Luckily CSS Tricks has some great articles on converting colour spaces which came in handy.
Sass renders before grabbing css variables
I had initially hoped to keep my
color-scale() sass manipulators with my new colours.
However, it turned out that when sass precompiles your css it doesn't know anything about those variable syet. It's just moving the string around, not looking into it. So trying to darken a string is obviously not going to work.
I was going to have to create all my variables as css variables for my theme colours and just reference them in sass.
Getting variables from our database and turning them into arrays of css variables.
Usually you would create css variables with a style tag. However it quickly became apparent that as I was using js to manipulate the styles anyway, having a script tag (to manipulate) inside a style tag (to set variables) felt.. icky.
getComputedStyle(document.documentElement) .getPropertyValue('--my-variable-name'); // #999999
People have some weird brand colours
OK so all well and good, I spat out the brand colour and then created an array of different lightnesses. Then in my
variables.scss I created variables from my variables.
Working through my templates, it was easy to grep
$brand-color and swap out with
$theme-color-10, 20, 30 etc. as I went along. What I didn't anticipate was how weird some teams' brand colours would be.
Very quickly on rolling out the theming we found some examples of borderline unusable UIs because some colours which look normal are actually pretty weirdly constructed (for example if saturation is really high and lightness is low, the colour looks muted. As soon as you drop that lightness, shit gets crazy).
So the final step was to block super high saturation. I chose to limit saturation to 60 with a
(s>60?60:s) on incoming saturation value. That's good enough for now.
- We're thinking of adding a package like color so we can detect luminosity. Only then will we be able to avoid accessibility issues and strange UI's.
- Frankly, the number of elements we've applied this to may be overkill. If it feels too much we may pull it back a bit, but for now it feels cool to have your Progression UI look like yours.
Enjoying these posts? Got any feedback? Feel free to email us at email@example.com.