Article illustration 1

When building dynamic particle animations, developers often encounter a subtle but frustrating limitation in CSS: animating between HSL colors frequently produces muddy, desaturated midpoints. This occurs because browsers convert HSL values to RGB for interpolation—a mathematical approach that doesn't align with human color perception.

The RGB Interpolation Problem

Consider this common scenario: transitioning a button from red (hsl(0deg 100% 65%)) to teal (hsl(180deg 100% 65%)):

button {
  background: hsl(0deg 100% 65%);
  transition: background 2000ms;

  &:hover {
    background: hsl(180deg 100% 65%);
  }
}

Despite vibrant start/end colors, the midpoint becomes gray as RGB channels converge:

"The browser transitions all three color channels independently, causing them to meet at #808080—a medium gray no designer would choose as the midpoint between red and teal."

Article illustration 2

Hue-Rotate to the Rescue

The solution lies in CSS filters. Instead of animating background-color, apply hue-rotate() for perceptual color shifts:

@keyframes hueRotate {
  to { filter: hue-rotate(720deg); }
}

.particle {
  animation: hueRotate 1000ms;
  background: hsl(var(--hue) 100% 80%);
}

JavaScript sets the initial hue:

const hue = Math.round(Math.random() * 359);
particle.style.setProperty('--hue', `${hue}deg`);

This approach maintains saturation and lightness while rotating through the color spectrum, avoiding desaturation. Two full rotations (720deg) ensure visible color shifts without abrupt jumps.

Advanced Techniques: Twinkling Effects

For added realism, combine hue rotation with randomized opacity variations:

@keyframes twinkle {
  from { opacity: var(--twinkle-amount); }
  to { opacity: 1; }
}

.particle {
  animation: 
    twinkle var(--twinkle-duration) infinite alternate,
    hueRotate 1000ms;
}

Varying --twinkle-duration and --twinkle-amount per particle prevents synchronized flickering, creating organic movement.

Why This Matters

Understanding color interpolation models is crucial for:
1. Implementing visually consistent animations
2. Avoiding unintended UX artifacts like desaturation
3. Leveraging performant CSS filters instead of heavy JavaScript solutions

The hue-rotate technique demonstrates how working with browser rendering behaviors—rather than against them—yields smoother, more vibrant results.

Article illustration 4

Source: Josh W. Comeau