by Odin Ravensson on
Your browser does not support scroll-driven animation. If you are using Firefox, set
layout.css.scroll-driven-animations.enabled to true on your about:config settings, and then
refresh this page.
Let’s make a scroll sensitive background! As I’ve been contemplating the styling on this site, I’ve been thinking about Sailor Moon and its twilit pink aesthetic. To emulate this, it would feel nice to have a page descend into nighttime when you scroll down it.
Let’s start with this palette:
:root {
--amaranth-pink: #f19cba;
--coronation-blue: #5b55a0;
--opal-blue: #0c3b68;
}
And now here are the two gradients I’d like to transition between:
:root {
--blue-to-pink: linear-gradient(var(--coronation-blue), var(--amaranth-pink) 50%);
--blue-to-blue: linear-gradient(var(--blue-opal), var(--coronation-blue) 50%);
}
Now let’s set up the keyframes:
@keyframes naive {
from { background: var(--blue-to-pink); }
to { background: var(--blue-to-blue); }
}
.naive-animation {
scroll-timeline-name: --self;
animation: naive 1ms linear;
animation-timeline: --self;
}
But, as you can see, it jumps from one to the other once we reach the halfway mark. The first step to get around this would be to animate the position of the stops.
:root {
--tricolor: linear-gradient(
var(--blue-opal), var(--coronation-blue) 25%,
var(--coronation-blue) 50%, var(--amaranth-pink) 75%)
}
@keyframes stops {
from { background-position: bottom; }
to { background-position: top; }
}
.stops-animation {
background: var(--tricolor);
background-size: 100% 200%;
scroll-timeline-name: --self;
animation: stops 1ms linear;
animation-timeline: --self;
}
But this just slides the gradient as if it were a static image, not as if it were a sunset transitioning into night.
There’s one more option to try using Houdini and @property registration. Here we get proper full-color interpolation
between gradients but the one drawback is that you have to use color primitive values and not CSS custom properties.
@property --houdini-start {
syntax: "<color>";
initial-value: #5b55a0;
inherits: false;
}
@property --houdini-end {
syntax: "<color>";
initial-value: #f19cba;
inherits: false;
}
@keyframes houdini {
from {
--houdini-start: #5b55a0;
--houdini-end: #f19cba;
}
to {
--houdini-start: #0c3b68;
--houdini-end: #5b55a0;
}
}
.houdini-animation {
background: linear-gradient(var(--houdini-start), var(--houdini-end) 50%);
scroll-timeline-name: --self;
animation: houdini 1ms linear;
animation-timeline: --self;
}
Now this is exactly the kind of vibe I wanted.