Typed Gradient Property Interpolation
A CSS gradient animation pattern that registers angle, hue, and stop-position custom properties so internal gradient values interpolate continuously instead of swapping whole strings.
A CSS gradient animation pattern that registers angle, hue, and stop-position custom properties so internal gradient values interpolate continuously instead of swapping whole strings.
Background / @property / gradient internals
Three gradient backgrounds animate registered internal values — angle, hue, and stop position — instead of swapping a full gradient string.
Registered angle
Register the angle and feed it into linear-gradient().
Registered hue
Animate hue as a typed number, not as a replaced color string.
Registered percentage
Animate the stop position while preserving the same gradient function.
Typed gradient interpolation registers angle, hue, and stop variables so CSS animates the internal gradient values instead of swapping whole gradients.
<div class="typed-gradient">Typed gradient</div><style>4@property --angle {syntax: '<angle>';inherits: false;initial-value: 120deg;}9@property --hue {syntax: '<number>';inherits: false;initial-value: 185;}14@property --stop {syntax: '<percentage>';inherits: false;initial-value: 46%;}.typed-gradient {--angle: 120deg;--hue: 185;--stop: 46%;width: 18rem;aspect-ratio: 16 / 9;display: grid;place-items: center;border-radius: 1rem;color: white;background:linear-gradient(var(--angle),32hsl(var(--hue) 86% 62%) 0%,hsl(calc(var(--hue) + 74) 78% 68%) var(--stop),hsl(calc(var(--hue) + 128) 80% 64%) 100%);animation: typed-gradient-shift 4.5s ease-in-out infinite;}@keyframes typed-gradient-shift {3950% { --angle: 250deg; --hue: 284; --stop: 68%; }}41@media (prefers-reduced-motion: reduce) {.typed-gradient { animation: none; }}</style>
Replacing a whole gradient string snaps between frames. A registered angle gives the browser real intermediate degrees.
Unregistered custom properties are parsed as tokens. Registering <angle> lets the browser interpolate through intermediate degrees.
Swapping named color stops jumps palettes. A numeric hue variable keeps the gradient structure stable while the color family moves.
Use a number when it feeds hsl(). Registering the full color is useful for different cases, but hsl hue math needs numeric values.
A hardcoded stop swap jumps the highlight. A registered percentage lets the stop position breathe through intermediate frames.
Percentage stops are numeric values. Registering them lets the highlight move through intermediate positions instead of jumping between gradient strings.
Stable declarations make interpolation predictable. Swapping whole gradient strings often falls back to a discrete jump.
Background-position moves an oversized image. This pattern changes the gradient values themselves.
Choose the safest contrast frame. Do not pause on a bright or low-contrast midpoint just because it is visually dramatic.
Typed gradient interpolation keeps the gradient string stable and animates its numeric internals. CSS custom properties are normally string-like unless the browser knows their syntax. Registering angle, hue, stop, or percentage values with @property lets the browser interpolate the underlying numbers continuously.
Use it when the animation needs to teach or expose how gradients change internally: angle turns, hue rotation, stop travel, or a controlled color sweep inside a stable surface. It is a good fit for technical demos, premium cards, and small branded surfaces. For a simple moving stripe, background-position is usually simpler and more predictable.
@property defines syntax such as <angle>, <number>, or <percentage>, plus inheritance and an initial value. The gradient references those variables, and keyframes change only the registered values so the browser can tween them rather than discrete-step the declaration.
Always include a static fallback before the registered-property version. Browser support, cascade order, and initial values all matter here; a missing registration can turn a smooth interpolation into a jump. If the inspector exposes hue, angle, or stop controls, every control must visibly change the gradient; unused sliders should not ship.
Animated gradients can pass through low-contrast frames. Test text at the worst frame, not just the starting frame, and keep the animated area bounded so it does not compete with page reading. Reduced motion should freeze the safest readable frame rather than swapping to a different effect.
This pattern is about animating gradient internals, not moving a gradient bitmap. Register angle, hue, and stop-position variables with @property so the browser can interpolate numeric pieces of the gradient continuously.
Unregistered custom properties often step discretely because the browser sees them as strings. Include a static fallback gradient, keep the animated area bounded, and verify the reduced-motion frame has enough contrast without depending on the sweep.
The implementation should make the typed value visible. Angle turns, hue shifts, and stop travel are different examples; changing only endpoint colors does not teach why @property matters.
Be conservative with inspector controls. Every exposed control needs to map to a registered variable or a real animation parameter, otherwise the snippet becomes misleading for users trying to copy the technique.