Recently I was asked how I would implement a series of effects. Part of this was the ability to transition between two different colours based on how far you had scrolled.
My original response to this was "you have to use a library". The justification for this is that because this is based on a scroll event and not time, you cannot use something like a native Web Animation to handle it as you need the ability to set the colour value of something at an arbitrary point of interpolation. There's no built in API for manipulating colours in such a way (unfortunately) so you're generally stuck having to use something like chroma.js or d3-scale.
However, this didn't sit well with me for a multitude of reasons. Firstly, including either of those libraries incurs a huge bundle filesize penalty for such a small feature.
Secondly, come on. There has to be a straightforward method of doing this, right? Surely it's not some kind of secret deep magic reserved for library authors.
After some deliberation, I had a general idea of what I needed to do but not how to do it. The process goes like this;
For a given interpolation i, get the start and ending colours and split them into their seperate red, green, and blue components (and alpha if you want transparency). Then for each colour component, get the value of distance i between the start and end value.
This last part caused me some grief until my quest led me to this wikipedia page on linear interpolation.
So after applying this transform to each colour component and combining them back into an RGB value, you have your final interpolated colour. For something like scroll, you simply need to convert the scroll offset to i such that it is in the range [0, 1].
With a little extra work, you can save tens of kilobytes off your client payload.
Here's a full example of colour lerping;