CSS @keyframes · Live Preview · CSS + Tailwind Output

CSS animated gradient generator

Build smooth, looping animated gradient backgrounds. Adjust colors, direction, speed and animation type — then copy the production-ready CSS or Tailwind arbitrary value.

135°
6s
300%

                

Why gradients cannot simply be animated

The obvious approach — a CSS transition on background-image between two gradients — does nothing in most situations. Gradients are images as far as CSS is concerned, and images have historically not been interpolatable, so the browser jumps straight from one to the other at the halfway point rather than blending.

The long-standing workaround is to animate something that is interpolatable and let the gradient come along for the ride. Declaring an oversized background-size, typically 300 or 400 percent, and animating background-position slides a large gradient across a small window, which reads as a smooth colour shift. It is a trick, but a robust one that works everywhere.

The modern alternative is genuinely animating the colours, using @property to register a custom property with syntax: '<color>'. Registration is what gives the browser a type, and with a type it knows how to interpolate. The gradient then references the custom property and animates properly, including with hard stops. This needs Chrome 85+, Safari 16.4+ and Firefox 128+, so a static fallback is still worth declaring.

What it costs to run

Not all animated properties are equal. Transform and opacity can be handled entirely by the compositor on the GPU, without the main thread doing per-frame work. Animating background-position cannot: it forces a repaint of the element on every frame, and the cost scales with the painted area. A full-viewport animated gradient behind a page is one of the more expensive things a CSS animation can do, and on a mid-range phone it will show up as a raised main-thread load and reduced battery life.

Adding will-change: background-position promotes the element to its own layer and can help, but each layer consumes memory proportional to its pixel area, and applying it broadly makes things worse rather than better. Use it on the one element that needs it, and remove it when the animation is not running.

Practical mitigations: keep the animated element as small as it can be while still reading as a background, prefer a slow cycle of fifteen seconds or more since gradual movement hides low frame rates, and check the result on a throttled CPU rather than a development machine. If the animation is decorative, pausing it when the element scrolls out of view via an IntersectionObserver costs a few lines and removes the expense entirely.

Respecting reduced motion

Large, continuously moving backgrounds are a genuine accessibility problem, not merely a taste question. For people with vestibular disorders, sustained motion in the periphery can trigger dizziness and nausea, and a slow full-screen colour shift is exactly the pattern that does it.

Operating systems expose a "reduce motion" preference and CSS surfaces it as @media (prefers-reduced-motion: reduce). Honouring it costs one media query: set animation: none and keep a static gradient, which loses nothing visually for a decorative background.

The stronger version of this is to treat motion as opt-in for anything running in a loop, since a gradient that animates once on load is far less troublesome than one that never stops. WCAG 2.2 success criterion 2.2.2 requires a mechanism to pause anything that moves automatically for more than five seconds, which an indefinite background animation does by definition. If you are auditing a page for this kind of thing, the notes in the contrast checker cover the related colour requirements.

Animated gradient FAQ

How does the CSS animation work?

The technique uses background-size set to 200–500% so the gradient is larger than the element, then animates background-position with @keyframes to shift the visible area — creating the illusion of flowing color without JavaScript.

Will it work in all browsers?

Yes. CSS @keyframes and background-position animation work in all modern browsers including Safari, Chrome, Firefox and Edge.

How do I apply it to text?

Add -webkit-background-clip: text; background-clip: text; color: transparent; to the same element. Note: gradient text (background-clip on text) has accessibility concerns — ensure sufficient contrast.

Why does transitioning between two gradients not work?

Gradients are images to CSS and are not interpolatable by default, so the browser swaps abruptly. Animate background-position with an oversized background-size, or register the colours with @property so they gain a type the browser can interpolate.

Is an animated gradient background expensive?

Yes, relatively. Unlike transform and opacity it repaints every frame, and the cost scales with area — a full-viewport gradient is one of the more demanding CSS animations. Keep it small and slow, and pause it when off-screen.