---
title: "How to Create an Animated Gradient Background in Framer"
description: "Build an animated gradient background in Framer — CSS position cycling, a mesh-gradient code override, performance tips, and a free component option."
canonical_url: "https://framerhub.io/blog/animated-gradient-background-framer"
last_updated: "2027-02-12T00:00:00.000Z"
---

An animated gradient background — colors that slowly shift and drift behind hero content — is one of the lowest-effort, highest-impact ways to make an otherwise flat section feel alive. It's also one of the effects where the difference between "subtle and premium" and "distracting and cheap" comes down almost entirely to speed and color choice rather than technical complexity. Here's how to build it properly, from a simple CSS version to a more advanced mesh gradient.

## Option 1: CSS Gradient Position Cycling (Simplest)

The lightest-weight version animates a large, oversized gradient's position within a fixed-size container, so different parts of the gradient scroll into view over time — no canvas, no WebGL, just a CSS `background-position` animation.

```jsx
import { motion } from "motion/react"

export function AnimatedGradientBG(Component): ComponentType {
  return (props) => (
    <motion.div
      style={{
        position: "absolute",
        inset: 0,
        backgroundImage:
          "linear-gradient(120deg, #7F5AF0, #2CB67D, #FF8906, #7F5AF0)",
        backgroundSize: "300% 300%",
      }}
      animate={{ backgroundPosition: ["0% 50%", "100% 50%", "0% 50%"] }}
      transition={{ duration: 16, repeat: Infinity, ease: "linear" }}
    >
      <Component {...props} />
    </motion.div>
  )
}
```

The key detail is `backgroundSize: "300% 300%"` — the gradient needs to be significantly larger than its container so there's meaningful travel distance as `backgroundPosition` animates, producing a genuinely flowing color shift rather than a barely perceptible wobble. At 100% size, the gradient can't move far enough within its own container to produce a visible effect.

This version is the right default for the majority of projects — it's a single CSS property being animated, costs almost nothing to render, and produces a convincingly fluid color shift with a fraction of the code and none of the performance overhead of a canvas or WebGL approach. Reach for the heavier mesh gradient technique in the next section only when the flatter, single-band motion of a linear gradient doesn't match the more organic, cloud-like look you're after — many hero sections genuinely don't need that extra visual complexity to look finished.

## Why Animated Gradients Became a Default Choice

Static gradients have been a design staple for years, but the animated version took off specifically because it solves a real problem flat hero backgrounds have: a large, single-color or single-gradient area can feel empty and inert, especially above a short headline with lots of surrounding negative space. A slow color drift fills that visual space with a small amount of ongoing life without adding any actual content, imagery, or complexity a visitor needs to process — it's motion that reads as atmosphere rather than information, which is exactly the kind of low-cognitive-load visual interest a hero section benefits from.

## Option 2: A Soft, Organic Mesh Gradient

For a more atmospheric, less directional look — closer to what's often called a "mesh gradient" or "gradient mesh" — layer several soft, blurred radial gradients and animate their individual positions independently.

```jsx
import { motion } from "motion/react"

const blobs = [
  { color: "#7F5AF0", size: 500, x: ["10%", "60%", "20%"], y: ["20%", "50%", "10%"] },
  { color: "#2CB67D", size: 450, x: ["70%", "20%", "80%"], y: ["60%", "20%", "70%"] },
  { color: "#FF8906", size: 400, x: ["40%", "80%", "30%"], y: ["80%", "40%", "60%"] },
]

export function MeshGradientBG(Component): ComponentType {
  return (props) => (
    <div style={{ position: "absolute", inset: 0, overflow: "hidden", filter: "blur(80px)" }}>
      {blobs.map((b, i) => (
        <motion.div
          key={i}
          style={{
            position: "absolute",
            width: b.size,
            height: b.size,
            borderRadius: "50%",
            background: b.color,
            opacity: 0.6,
          }}
          animate={{ left: b.x, top: b.y }}
          transition={{ duration: 20 + i * 4, repeat: Infinity, ease: "easeInOut" }}
        />
      ))}
      <Component {...props} />
    </div>
  )
}
```

Each colored blob drifts independently along its own path at its own speed (`20 + i * 4` staggers the durations so the blobs never fall into a synchronized, repetitive-feeling loop together), and the heavy `blur(80px)` on the wrapping container is what merges the individually crisp circles into soft, organic color fields rather than visible, hard-edged shapes.

## Choosing Colors That Work Together

The single biggest quality factor in this effect isn't the animation technique — it's whether the color palette actually harmonizes. A few practical rules:

- **Stay within 2-4 colors.** More than that and the gradient starts to look muddy rather than rich, especially once blurred.
- **Pick colors adjacent on the color wheel, or use one strong accent against 2-3 muted neutrals.** Full-spectrum rainbow gradients read as generic and dated rather than premium.
- **Check the gradient against your actual foreground content**, not in isolation. A gradient that looks beautiful as a standalone background can still fail if your headline text doesn't have sufficient contrast against every color the gradient cycles through — test the full animation cycle with your real content on top, not just a single static frame.
- **Pull colors from your existing brand palette rather than introducing new ones specifically for this effect.** A gradient background is one of the more visually dominant elements on a page — if its colors don't relate to the rest of your brand's palette, the hero section can end up feeling disconnected from the rest of the site rather than like a cohesive extension of it.

Tools like Coolors or a color-wheel picker built into most design software can help verify whether a chosen set of colors is genuinely harmonious before you commit to animating between them — a combination that looks fine as separate static swatches can still clash once blended together in a moving gradient, since the in-between transition colors matter as much as the endpoints themselves.

## Speed: Slower Than Feels Necessary

A background gradient's job is to feel ambient, not to be watched — most well-executed examples run a full cycle in 12-25 seconds, meaningfully slower than most first attempts, which tend to animate closer to 3-6 seconds out of an instinct to "make sure it's visible." A background moving that fast competes with foreground content for attention rather than supporting it. If you find yourself able to consciously track the gradient's motion while reading the headline in front of it, it's very likely moving too fast for a background role.

## Drop-In Option: Aurora

If you'd rather not hand-tune blob paths and gradient stops, FramerHub's [Aurora component](/components/aurora) is a free, ready-made animated gradient background with color, speed, and blur exposed as property panel controls — a northern-lights-style soft gradient wash that drops straight into a hero section. It's part of FramerHub's [component library](/components), browsable through the [Components plugin](/plugins/framer-components) alongside other background and visual effects if you're assembling a fuller hero section.

## Performance Notes

The CSS `background-position` approach (Option 1) is cheap to run continuously — it's a well-optimized property for browsers to animate. The blurred multi-blob mesh approach (Option 2) costs more, since a large `filter: blur()` applied over a big area is more GPU-intensive than a plain gradient, and it compounds with however many blobs you're animating simultaneously. For a full-viewport hero background specifically, test the mesh version on a mid-range device — three or four blobs is a reasonable ceiling before the blur cost starts noticeably affecting scroll and animation smoothness elsewhere on the page.

## Where This Effect Works Best

- **Hero section backgrounds**, especially for SaaS, AI, and creative-tool brands where a soft, colorful atmosphere supports the brand tone without competing with headline copy.
- **Section dividers or CTA backgrounds** further down a page, adding visual variety without introducing a new photographic or illustrated asset.
- **Loading or empty states**, where ambient motion fills otherwise static screen real estate.

It's a poor fit for content-dense, information-heavy sections (dashboards, pricing tables, dense text) where a moving background actively competes with the reading task rather than supporting a moment of atmosphere.

## Accessibility

As with any continuous background animation, respect `prefers-reduced-motion` — pause the animation or fall back to a single static gradient frame for visitors who've set that preference, since the moving color is purely decorative and carries no information that's lost by holding it still.

## Common Mistakes

- **Animating too fast.** As covered above, this is the single most common issue — an eye-catching, rapidly shifting gradient competes with foreground content instead of supporting it.
- **Too many colors in one gradient.** Beyond 3-4 colors, especially once blurred, gradients tend to muddy into a grayish or brownish blend at the transition zones rather than staying vibrant throughout the cycle.
- **Not testing contrast across the full animation cycle.** A gradient that starts with great text contrast can drift into a color combination with poor contrast partway through its loop — check the whole cycle, not just the first frame.
- **Using the heavy mesh-blob technique when the simpler linear gradient would do.** Reach for the more expensive multi-blob approach only when the flatter look genuinely doesn't achieve the desired atmosphere — added rendering cost should be a deliberate tradeoff, not a default.

## FAQ

**Can I animate a gradient background in Framer without code?**
You can fake a simple version with a variant transition between two gradient fills, but a genuinely smooth, continuous color shift needs a code override animating background-position or gradient color stops directly, which Framer's native variant system isn't built to interpolate.

**What's the difference between an animated linear gradient and a mesh gradient?**
A linear gradient animates a straight color band's position or angle. A mesh gradient blends multiple soft color blobs at different points across the canvas, producing a more organic, less directional look — mesh gradients are more visually complex and are usually rendered with canvas or WebGL rather than pure CSS.

**Will an animated gradient background hurt performance?**
A CSS-based animated gradient (background-position or background-size cycling) is cheap. A canvas or WebGL-based mesh gradient is more expensive and should be tested on mid-range devices, especially if it covers a large area like a full-viewport hero background.

**How slow should a background gradient animation be?**
Slower than most people expect — 8 to 20 seconds per full cycle is typical for a background element, since it's meant to feel ambient and barely perceptible in the moment rather than a focal point you consciously track.

**Does an animated gradient background need to respect prefers-reduced-motion?**
Yes — even a slow, subtle background animation can be uncomfortable for motion-sensitive visitors if it runs indefinitely. Pause it or replace it with a static gradient snapshot when that preference is set.
