Sorry, looks like the code here is taking a while to load.
View not-for-project-consumption.scss on GitHub instead.
There’s nothing wrong with teaching conditionals with that. It’s easy to read and understand, and like best examples, it’s applicable to real life.
It has a problem, though, and that problem is that people start using it in their projects. I did too, until I realised that setting
$button-color to e.g.
blue will produce black text that is then completely illegible!
Fiddling with the threshold won’t help much. There’s always some case that triggers the wrong text colour.
To see what I mean more clearly, take a look at the demo below.
What’s the catch then? After a bit of searching, I found a great Thoughtbot article called A Closer Look at Color Lightness by Reda Lemeden. I quoted a few of his handy definitions.
The article explains the situation better than I ever could, so go take a look at it.
Odd behaviour occurs, because lightness is a non-weighted measure. In the HSL colour model for example, changing the hue will change the perceived brightness, but the lightness value will stay the same. This makes comparing lightness an unreliable method for judging perceived brightness, and by extension for judging readability.
After running some tests that you can also try yourself, Lemeden recommends using a weighted measure named sRGB luma as a good approximation for most use cases. The article has a fantastic graph of the different methods tested.
The snippets he shared include a function for Sass, but that one only returns if a colour is light or dark. It’s useful, but I wanted a one-liner so I could avoid writing ifs all the time. I decided to do some modifications to it.
This first one,
_luma.scss, just calculates the luma of a colour based on the equation from the article.
The second one is where the logic happens. It provides a function with the signature
pick-visible-color($bg-color, $color-1, $color-2).
It takes a background colour and two potential (e.g. text) colours. It then calculates their luma values and returns the colour that has the greater luma difference compared to the background colour.
Copy and paste the previous gists or download the raw files into your project’s files. I recommend creating a separate directory for them and other reusable functions.
Import the function into your file. Now you can simply write
color: pick-visible-color(...) and you’ll get a contrasting colour combination. Neat!
Below is a quick example if you need clarification.
While researching colour perception for this article (and subsequently just for fun), I found this fascinating “Colors and Colorimetry” overview by David Madore. It explains light, colour, the concept of “white” and more. Go check it out if you’re interested.