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.

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

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

Opens the CSS Gradient Builder with this page's checklist shown at the top of the tool.

Open in the tool →

@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.4

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.5 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/

  4. 4.

    World Wide Web Consortium, "CSS Color Module Level 4," drafts.csswg.org, September 2026. https://drafts.csswg.org/css-color-4/

  5. 5.

    Una Kravets, "@property: Giving Superpowers to CSS Variables," web.dev, July 2020. https://web.dev/articles/at-property

FAQ

The CapyToolkit gradient builder outputs the base gradient value with your chosen stop colors, giving you a reliable starting point for moving the stops into typed tokens without hand-writing the initial color values. Browsers cannot interpolate between two background-image values directly. Without @property, transitioning a gradient changes the entire image value discretely at the 50% point. Register each stop color as a typed @property custom property and reference it inside the gradient to enable smooth interpolation.

Chromium 85+ (Chrome, Edge, Opera) and Safari 16.4+ support @property with typed custom properties. Firefox added support in version 128. For broader compatibility, use the background-position shimmer technique instead: it requires no @property and works in all modern browsers.

Register the start and end stop colors as typed color properties with @property, then set oklch() values in the @keyframes rule and use in oklch interpolation in the gradient function. The OKLCH interpolation routes the blend through the perceptual color space, eliminating the grey midpoint sRGB produces between complementary hues.

animation-timeline links a CSS animation to a scroll or view timeline instead of the default document time. Setting animation-timeline: scroll(root) makes the animation progress as the user scrolls. Combine it with a @property-driven gradient animation to create gradients that shift with scroll position, replacing JavaScript scroll listeners for this use case.

Yes, with @property. Register a separate custom property for each stop that needs animation, such as stopOne and stopTwo. Each property gets its own @keyframes rule or shares a single rule with different from/to values. Reference each property in the gradient function. Each stop can animate at a different rate or duration by assigning different animation properties to each custom property.

Additional resources

Guides

CSS Gradient Text with background-clip Apply a CSS gradient to text using background-image and background-clip: text. Browser support, fallback strategy, and live examples with the gradient builder. Animating CSS Gradients with @property Animate CSS gradient stops smoothly using @property custom properties. Browser support, fallback patterns, and OKLCH hue-rotation animations. CSS Mesh Gradient Technique Build mesh-style gradients in CSS using multiple layered radial-gradient() values on the same background-image. No SVG or canvas required. Tailwind CSS v4 Gradient Utilities Complete guide to Tailwind v4 gradient utilities. bg-linear-to-r, bg-radial, bg-conic, from-*, via-*, to-*, and in-oklch modifier reference. CSS Gradient Borders Apply CSS gradient borders using border-image or background-clip masking. Both techniques, browser support comparison, and border-radius workaround. OKLCH Interpolation in CSS Gradients Use OKLCH color space interpolation in CSS gradients with the in oklch modifier. How it eliminates grey midpoints and improves perceptual smoothness. CSS Gradients for Dark Mode UI Design CSS gradients for dark mode using reduced chroma, lower lightness stops, and prefers-color-scheme media queries. Practical patterns for UI surfaces. CSS Background Patterns with Gradients Build repeating CSS background patterns using gradient functions and background-size. Stripes, grids, dots, and diagonal tile techniques without images. Glassmorphism with CSS Gradients Implement the glassmorphism effect with CSS gradients, backdrop-filter blur, and translucent stops. Browser support and performance considerations. CSS Gradient Rendering Across Laptop and Phone Displays How CSS gradients render on the Dell XPS 16, iPhone 17 Pro, MacBook Air M4, MacBook Pro M4 and Galaxy S25: P3 color stops, OKLCH interpolation, OLED blacks and the browser engine each device runs.