Free · Fast · Privacy-first

CSS Gradient Animation

Animated gradients bring hero sections, loading states, and ambient backgrounds to life without any JavaScript.

Generates background-position @keyframes animation CSS

🔒

Configure animation duration, timing function, and direction

Works without JavaScript in all modern browsers

Output includes gradient, background-size, and animation declarations

Cost
Free forever
Sign-up
Not required
Processing
In your browser
Privacy
Files stay local
FreeNo signupWhite-label

Add this Gradient to your website

Drop the Gradient into any page — blog post, product docs, intranet, school portal — with a single line of HTML. Your visitors get the full tool, processed entirely in their browser. No backend, no uploads, no signup.

  • Files stay 100% in the visitor's browser
  • Responsive — adapts to any container width
  • Free forever, no API key needed

Embed code

<iframe
  src="https://www.fixtools.io/css-tool/gradient?embed=1"
  width="100%"
  height="780"
  frameborder="0"
  style="border:0;border-radius:16px;max-width:900px;"
  title="Gradient by FixTools"
  loading="lazy"
  allow="clipboard-write"
></iframe>

Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.

How CSS Gradient Animations Work: background-size and background-position

CSS cannot directly animate gradient colour stop values using transition or animation because gradient functions are not registered as interpolatable property value types by browser layout engines. The browser cannot calculate a valid midpoint state between two different gradient declarations, so attempts to animate the gradient itself produce no visual transition. The standard workaround for animated gradient backgrounds exploits the background-position property, which is fully animatable, alongside an oversized background-size. Setting background-size: 400% 400% creates a gradient image that is four times wider and taller than the element. The element acts as a fixed viewport into this larger gradient. Animating background-position with @keyframes moves this viewport across the oversized gradient, bringing different colour regions into view at different points in the animation timeline. From the viewer's perspective, the colours appear to flow, shift, and breathe continuously, even though the gradient itself never changes.

The technique requires three CSS declarations on the animated element working in coordination. First, the background property sets a multi-stop gradient with enough distinct stops to create visual interest across the full animation cycle. Four stops are the practical minimum for a smooth, believable looping colour shift. Second, background-size is set to 200% or larger (400% is most common) to give the animation room to travel without exhausting the gradient range before the loop point. Third, the animation shorthand references a @keyframes block that moves background-position between two or more coordinate states. The most effective keyframe pattern moves background-position through three waypoints (0% 50%, 100% 50%, and back to 0% 50%) to create a seamless round-trip loop. The animation-timing-function controls the easing character: ease-in-out produces a slow, meditative pulsing quality; linear creates constant flow; ease creates a rush-and-settle pattern.

FixTools generates the complete animated gradient CSS block: the gradient declaration, the background-size property, the animation shorthand with configurable duration and timing function, and the @keyframes rule. The output is a complete, self-contained CSS block that you can copy and paste directly into your stylesheet. Apply the block to any element and the animation begins immediately without any further configuration or JavaScript involvement.

Battery and CPU implications of animated gradients are worth understanding for any project where mobile users are a meaningful audience. A continuously animating background-position runs every frame for as long as the animated element is on screen, which keeps the GPU active and can prevent the device from entering low-power compositor states. On desktop hardware the impact is negligible. On mobile, particularly on entry-level Android devices, a full-viewport animated gradient on the body element can measurably reduce battery life over an extended browsing session. Two mitigations help. Use the Intersection Observer API or pure CSS animation-play-state to pause the animation when the element is outside the viewport. Also consider pausing animation on document visibilitychange when the tab is hidden, so the animation does not continue burning battery while the user is on another tab or has their phone locked.

How to use this tool

💡

Generate an animated gradient. Example output: background: linear-gradient(270deg, #ee7752, #e73c7e, #23a6d5, #23d5ab); background-size: 400% 400%; animation: gradientShift 8s ease infinite;

How It Works

Step-by-step guide to css gradient animation:

  1. 1

    Open the CSS Gradient Generator

    Navigate to the FixTools CSS Gradient Generator and open the configuration panel. For animated gradients, the generator outputs additional CSS beyond the gradient itself, including the background-size property, the animation shorthand declaration, and the @keyframes block needed to drive the position animation.

  2. 2

    Choose four or more colour stops

    Add at least four colour stops to your gradient configuration so the animation has enough colour range to cycle through without a visible or jarring loop restart. Arrange the stops so the last colour is tonally similar to the first, which ensures the animation loop appears seamless and continuous when it restarts.

  3. 3

    Configure animation settings

    Set the animation duration to 6 to 15 seconds for smooth ambient background effects, or 1 to 3 seconds for loading shimmer and interactive button effects. Choose ease-in-out for an organic breathing quality or linear for constant directional flow. The preview panel shows the animated result before you copy the code.

  4. 4

    Copy the full animation CSS block

    Copy the complete output block from the panel: this includes the gradient background declaration, the background-size rule, the animation shorthand with the keyframe name, and the @keyframes rule itself. All four components are required for the animation to function correctly when applied to your element.

Real-world examples

Common situations where this approach makes a real difference:

Animated hero section background

A startup homepage uses a slowly flowing gradient background on the hero section to convey dynamism and forward momentum without relying on video or heavy image assets. The developer generates a four-stop gradient spanning the brand colour palette from warm orange through rose pink to bright cyan, sets background-size: 400% 400%, and creates a @keyframes block animating background-position from 0% 50% to 100% 50% and back over 10 seconds with ease-in-out timing. The result is a gently shifting colour field that adds ambient energy to the hero without overwhelming or distracting from the headline and call-to-action.

Loading skeleton shimmer

A content feed displays skeleton placeholder blocks while data loads from the server API. Each skeleton element uses a three-stop horizontal gradient: medium grey at 0%, a noticeably lighter grey at 50% for the highlight peak, and medium grey again at 100%. background-size: 200% 100% is set and background-position animates from 100% 0 to -100% 0 over 1.5 seconds with a linear timing function set to iterate infinitely. The single-axis horizontal travel produces the characteristic left-to-right shimmer sweep that immediately signals loading state to users without requiring any JavaScript animation library.

Button gradient shift on interaction

A prominent call-to-action button uses an animated gradient triggered on hover to signal interactivity and reward user attention. The default state uses background-size: 100% 100% with no animation applied. On :hover, background-size switches to 200% 200% and a short 0.4-second background-position animation runs exactly once (animation-iteration-count: 1). The gradient appears to shift directionally as the user hovers, creating a tactile and satisfying hover response without altering button dimensions, changing layout, or triggering any reflow or repaint beyond the GPU-composited background-position change.

Page-wide gradient canvas for a creative portfolio

A creative portfolio uses a full-viewport animated gradient as the ambient page canvas across which all content sections are layered. The body element receives a seven-stop hue-rotation gradient with background-size: 600% 600% and a 20-second linear infinite animation continuously shifting background-position across both axes. The slow and constant colour cycle creates an ever-changing atmospheric canvas reminiscent of gradient mesh design tools. All readable content sits above this canvas on white-background cards with box shadows, ensuring full legibility while the animated canvas provides ambient visual energy below.

When to use this guide

Use this when you need a gradient that moves, shifts, or flows over time, creating a dynamic background effect with pure CSS and no JavaScript.

Pro tips

Get better results with these expert suggestions:

1

Use at least four colour stops for smooth looping animations

With only two or three stops, an animated gradient can reveal a jarring colour jump at the loop point where the animation restarts, because the end of the gradient range is visually very different from the beginning. Using four or more stops, and arranging them so the last colour is similar in tone to the first, creates enough visual buffer that the loop point becomes imperceptible. Aim for a colour arrangement where the first and last stops share a similar hue or lightness, allowing the cycle to repeat without any visible discontinuity.

2

Set animation-timing-function: ease-in-out for organic breathing

The ease-in-out timing function makes the gradient slow down at the extremes of its background-position travel range and accelerate through the middle. This creates a breathing, pulsing quality to the colour shift that feels organic and natural rather than mechanical and robotic. For slower, more ambient and meditative atmospheric effects, set the animation duration to 10 to 15 seconds. For energetic, attention-grabbing effects appropriate for promotional landing pages, use 3 to 5 seconds with a linear timing function.

3

Use prefers-reduced-motion to respect user accessibility preferences

A meaningful portion of users experience discomfort, dizziness, or cognitive difficulty with animated backgrounds. Always wrap gradient animation declarations inside a @media (prefers-reduced-motion: no-preference) block so the animation only runs for users who have not requested reduced motion. Users with prefers-reduced-motion: reduce will see the static version of the gradient without any movement. This satisfies WCAG 2.1 Success Criterion 2.3.3 and makes the page more accessible to users with vestibular disorders or attention-related sensitivities.

4

Layer a static radial gradient over an animated linear gradient

Combine two comma-separated background values where the first is a static radial gradient and the second is the animated linear gradient: background: radial-gradient(circle at 50% 0%, rgba(255,255,255,0.15) 0%, transparent 60%), linear-gradient(270deg, #ee7752, #e73c7e, #23a6d5). Set background-size: auto, 400% 400% to animate only the second layer. The static radial overlay adds a fixed, centred top-light highlight while the linear gradient colours shift beneath it, producing a layered depth effect far more complex than a single animated gradient alone.

FAQ

Frequently asked questions

Standard CSS cannot animate gradient colour stops with transition or animation because gradient functions are not registered as interpolatable value types in the CSS specification. The browser layout engine cannot calculate midpoint values between two different gradient declarations, so no visual interpolation occurs. The background-position workaround is the most widely supported solution: it animates a different property (position) against an oversized gradient rather than the gradient itself. CSS @property registration offers a newer approach for animating individual colour values inside a gradient function, supported in Chrome, Edge, and Safari from late 2023 onward.
The technique works by setting background-size to a multiple of 100% (typically 200% to 400%) to make the rendered gradient image significantly larger than the visible element area. The element then shows only a portion of this oversized gradient through its boundaries. Animating background-position with @keyframes moves the element's effective viewport across the larger gradient, causing different colour regions to become visible at different times. From the viewer's perspective, the colours appear to shift and flow organically, even though only the viewport position is changing and the gradient declaration itself remains static throughout the animation.
For ambient background effects on hero sections and full-page canvases, 8 to 15 seconds produces a slow, gentle breathing quality that adds visual interest without distraction. For loading state skeleton shimmers, 1 to 2 seconds matches standard user expectations for loading indicator speed and conveys urgency without being frantic. For hover-triggered interactive animations on buttons and cards, 0.3 to 0.5 seconds provides immediate and satisfying interactive feedback. Always test on representative hardware: GPU-accelerated gradient animations run smoothly at any duration, but older mobile devices may show frame drops on very large animated gradient elements.
Use animation-iteration-count: infinite and design the @keyframes block so the animation returns to its starting state before repeating. The most reliable pattern for seamless loops uses three keyframe waypoints: 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; }. This creates a round-trip animation that reaches the far position at the midpoint and returns to the starting position at 100%, making the loop restart invisible. As an alternative, animation-direction: alternate automatically reverses the keyframes on each iteration, achieving the same round-trip effect with a simpler two-waypoint @keyframes block.
CSS background-position animation is GPU-composited in all modern browsers and does not trigger layout or paint cycles, making it one of the most performance-efficient types of CSS animation available. However, on large full-viewport elements or on mobile devices with constrained GPU memory, complex gradient animations can increase per-frame GPU work. Adding will-change: background-position to the animated element hints to the browser to pre-promote the element to its own compositor layer, which can improve frame timing consistency. For performance-critical cases, reduce the background-size multiplier and simplify the gradient stop count to the minimum needed for the visual effect.
Wrap the animation declaration inside @media (prefers-reduced-motion: no-preference) so it is only applied for users who have not requested reduced motion: @media (prefers-reduced-motion: no-preference) { .hero { animation: gradientShift 8s ease-in-out infinite; } }. Users whose operating system accessibility settings include reduced motion will see the static gradient background without any movement. This satisfies WCAG 2.1 Success Criterion 2.3.3 (Animation from Interactions) and makes the page more accessible to users who experience vestibular disorders, motion sickness, or attention difficulties triggered by continuously moving background elements.
Yes. The background-position animation technique works in all modern versions of Safari, including Safari on iOS and iPadOS, without any vendor prefixes or special handling. Safari requires the -webkit-background-clip: text prefix only when you are animating gradient text effects using the background-clip technique. For regular animated background gradients, no prefixes are needed. Very old Safari versions from before 2014 have limited CSS animation support, but those browser versions represent well under 0.5% of current web traffic globally and do not warrant special accommodation in most projects.
Pure CSS scroll-triggered gradient animations are possible using animation-timeline: scroll() available in Chrome and Edge from version 115 onward (scroll-driven animations specification). Set animation-timeline: scroll() on the gradient element and remove the animation-duration; the scroll position within the defined scroll range drives animation progress instead of elapsed time. This makes the gradient shift in response to how far the user has scrolled rather than in response to time. Safari and Firefox support for scroll-driven animations is arriving in their 2024 and 2025 release versions; provide a fallback static gradient or JavaScript-based alternative for browsers that do not yet support the feature.
Three causes account for most mobile gradient animation stutters. First, the animated element is too large: a full-viewport gradient on a 4K-equivalent mobile browser viewport requires the GPU to composite millions of pixels per frame. Reduce the element size or limit the animation to a smaller decorative region. Second, the background-size multiplier is too high: 600% or 800% multipliers create very large texture buffers that exceed GPU memory limits on low-end devices. Reduce to 200% or 300% if visual quality allows. Third, other animations on the page are competing for compositor resources. Open the Chrome DevTools Performance panel on the device, record during the stutter, and check whether layout or paint events are firing alongside the gradient animation. A clean recording with only compositor activity indicates the gradient itself is the bottleneck.
A CSS gradient animation costs essentially nothing in payload, decodes nothing, and has no third-party library dependency. Lottie animations require the Lottie player library (about 70KB minified) plus the animation JSON file (typically 10 to 100KB), and they run on the JavaScript main thread for parts of their rendering. Video backgrounds carry the highest cost: even a short 5-second loop encoded as WebM at 1080p easily exceeds 500KB, requires a decode pipeline that ties up codec hardware, and forces autoplay handling for mobile browser policies. For pure colour-shift effects, animated CSS gradients are dramatically more efficient. For complex illustrated motion or photographic content, Lottie or video remain the right tools because CSS gradients cannot replicate detailed visual content.

Ready to get started?

Open the full Gradient — free, no account needed, works on any device.

Open Gradient →

Free · No account needed · Works on any device