Animating CSS Gradients with @property

Build linear, radial, and conic CSS gradients with a visual editor. Drag color stops, pick presets, and copy ready-to-use CSS, Tailwind, or custom property output.

ZERO UPLOAD · ALL LOCAL
  1. Choose a gradient type with the Linear / Radial / Conic toggle, or click a preset to load a starting point.
  2. Click anywhere on the gradient track to add a color stop, then drag it left or right to reposition it.
  3. Click a handle to select it, then type any CSS color format (HEX, RGB, HSL, or OKLCH) into the color field, or use the swatch to open the browser color picker.
  4. Drag the angle dial to rotate a linear gradient or set the starting angle for a conic gradient. For radial and conic types, set the center position with the X and Y inputs.
  5. Choose CSS, Tailwind, or Vars in the output panel and click Copy to grab the result.

What this page covers

  • @property registration required to animate gradient stop colors directly
  • background-position-x animation the no-@property fallback that works in all modern browsers
Gradient Type
Presets
Color Stops
0 50 100
Angle
135° deg
Results
 

Animating CSS Gradients with @property

Animating CSS gradients requires choosing between two fundamentally different techniques, and the right choice depends on whether the stop colors themselves need to change or only the visible position of a fixed gradient. Without @property, browsers cannot interpolate between two background-image values and snap abruptly at the transition midpoint.1 With @property, you register a custom property as a typed color, and the browser interpolates it smoothly in any @keyframes rule.

The background-position shimmer technique animates gradient position rather than stop colors, requiring no @property support and producing smooth results in every modern browser. For OKLCH hue-rotation animations, @property is the only CSS-only path: register two custom properties as type color, set oklch values in @keyframes, and the browser rotates through hues perceptually. This distinction matters because stop-color animation creates new gradient textures as colors change, while background-position animation reuses the same texture and only changes its offset. The CSS Scroll-Driven Animations spec adds animation-timeline for linking gradient animations to scroll position without JavaScript.2

@property custom property animation for gradient stops

Registering a custom property with @property gives it a type, an initial value, and an inheritance setting. A property registered as type color is animatable: @keyframes rules can interpolate between two color values assigned to it. Using this property inside a gradient function produces smooth stop-color animation.1 Without this registration, the browser treats the custom property as an untyped string and cannot interpolate between its values in keyframes.

Registering a color token

The @property block goes at the top of the stylesheet and declares a typed color token for the first stop. A @keyframes rule then transitions that token from blue to orange. Applying the animation to the element and referencing the token in the gradient function makes the stop color animate smoothly. Consequently, each stop that needs animation requires its own registered property. Building on this, multiple properties can animate independently in the same gradient, producing complex multi-stop color shifts that move through different hues at different rates within a single animation cycle.

Because each animated stop needs its own registered property, a gradient that moves only one accent color registers a single token, while a three-stop gradient that animates every stop registers three. Keeping the registration count to the minimum number of stops you actually animate avoids unused declarations and makes the stylesheet easier to maintain. CapyToolkit's gradient builder emits the typed tokens alongside the gradient so the registration and the function stay in sync.

Background-position shimmer as a fallback

background-position animation requires no @property support and works in all modern browsers. Set the gradient background-size to 200% 100% (or wider), then animate background-position-x from 100% to 0% or 0% to 100%. The gradient appears to slide across the element, creating a shimmer or sweep effect. Because the browser repositions an existing texture rather than repainting the gradient on each frame, this technique scales to dozens of simultaneously animating elements without degrading scroll or interaction responsiveness on lower-powered mobile hardware.3

When to prefer background-position

This approach changes which part of the gradient shows through the element, not the actual stop colors. The gradient colors remain fixed; only the visible window moves. Yet it produces a convincing color-shift animation because different hues enter and leave the element area. Furthermore, background-position animations trigger neither layout nor paint on the main thread in browsers that composite background animations on the GPU, making this approach ideal for performance-sensitive UIs where layout stability matters. For skeleton loading states and button hover effects where broad browser support matters more than stop-color precision, background-position animation delivers smooth results without any @property detection or fallback logic. Because the browser repositions an existing texture rather than repainting the gradient on each frame, this technique scales to dozens of simultaneously animating elements without degrading scroll or interaction responsiveness.

OKLCH hue-rotation and animation-timeline

OKLCH hue-rotation animates the H (hue) component of an oklch() color across the full 0-360 range. Once you pick the oklch stop your hue rotation starts from, you register a numeric hue token, animate it from 0 to 360 in @keyframes, and use that token as the hue component of the oklch() gradient stop to rotate through all hues smoothly. The perceptual uniformity of OKLCH means the lightness and chroma remain visually consistent throughout the rotation.

The CSS Scroll-Driven Animations spec adds animation-timeline: scroll() and animation-timeline: view() as alternatives to time-based animations. Linking a gradient animation to scroll position with animation-timeline: scroll(root) makes the gradient shift as the user scrolls the page.2 Consequently, a hero section gradient that responds to scroll position requires no JavaScript event listeners. Yet browser support for scroll-driven animations requires Chromium 115+ or Safari 18+; a fallback @keyframes rule ensures the gradient appears correctly in older browsers without the scroll-linked behavior. Combining scroll-driven animation with OKLCH hue rotation produces a gradient that travels through the full color spectrum as the reader scrolls, creating a visual reading progress indicator that also serves as a decorative design element.

@property support matrix and defensive fallback patterns

@property is supported in Chrome 85+, Edge 85+, Firefox 128+, and Safari 16.4+ as of mid-2026. Browsers that predate these versions treat a registered custom property as an untyped plain variable, which means the gradient stop color assigned to it cannot be interpolated. The animation still runs, but the browser snaps from the start value to the end value at the 50% mark rather than blending smoothly.

Building a defensive fallback requires separating the static and animated layers. Write the gradient with hardcoded stop colors as the base rule, then wrap the @property registration and keyframes animation in a @supports (background: paint(id)) block, which acts as a rough indicator of Houdini API availability. A simpler approach: accept that browsers without @property see the static gradient as a complete design, not a broken one, and ship the @property animation as a progressive enhancement without a complex detection strategy.

Testing @property gradient animations across browsers

Verifying @property animations across browsers requires testing in at least Chrome, Firefox, and Safari. DevTools in Chrome shows @property registrations under the Registered Properties section in the Sources panel. Inspecting the registered grad-from property and its initial-value confirms that the registration parsed correctly. In Safari, the Web Inspector Elements panel shows the computed CSS custom property value, which reveals whether the typed animation is updating the property correctly during playback.

When to use this

Use @property gradient animation for hero sections and brand moments where color movement reinforces a visual identity. Use background-position shimmer for lightweight loading indicators and button hover states where broad browser support matters more than stop-color animation.

Examples

Hero background gradient that rotates through OKLCH hues on scroll

Register --hue as type number with @property. Use animation-timeline: scroll(root) and animation-range: 0% 50% to link the hue rotation to the first half of the page scroll. Requires Chromium 115+ or Safari 18+.

Shimmer loading skeleton with background-position animation

Set background: linear-gradient(90deg, var(--bg-raised) 0%, var(--bg-surface) 50%, var(--bg-raised) 100%) and background-size: 200% 100%. Animate background-position-x from 200% to -200% with a 1.5-second linear loop. Works in all modern browsers without @property.

Button with animated gradient border on hover

Use a ::before pseudo-element with the gradient background and clip it behind the button content. On hover, animate --grad-from and --grad-to with @property registered colors. The border gradient shifts color smoothly on hover without affecting the button layout.

Sources
  1. 1.

    Mozilla Developer Network, "@property," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/CSS/@property

  2. 2.

    Mozilla Developer Network, "animation-timeline," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timeline

  3. 3.

    Agop Bashi, "Compositor-Only Property Optimization," css-animation.com, accessed June 2026. https://www.css-animation.com/performance-budgeting-gpu-architecture/compositor-only-property-optimization/

FAQ