---
title: "How to Create a Progressive (Gradient) Blur in Framer"
description: "Build a progressive, gradient blur in Framer using layered backdrop filters — the working code, layer-count tuning, and where the effect fits best."
canonical_url: "https://framerhub.io/blog/progressive-blur-framer"
last_updated: "2027-02-17T00:00:00.000Z"
---

Progressive blur — where blur intensity increases gradually across a direction, sharp on one edge and heavily blurred by the other, rather than one uniform blur value everywhere — has become a signature detail on modern product sites (Linear, Vercel, and a growing list of others use it on their navigation bars specifically). It looks deceptively simple and is genuinely impossible to build with a single CSS property. Here's the actual technique.

## Why a Single `backdrop-filter` Can't Do This

`backdrop-filter: blur(20px)` accepts one numeric value — the entire filtered area gets exactly that much blur, uniformly. There's no native CSS syntax for "blur 0px on this edge, ramping up to 20px on that edge." A CSS `mask-image` can control where an effect is visible or hidden, but it can't vary the *intensity* of a filter across space — it's a binary (or gradient-opacity) visibility mask, not a value interpolator.

The workaround the industry has converged on: stack several blurred layers on top of each other, each with a **different blur amount** and a **different mask position**, so that different regions of the final composite are dominated by different layers. The combined visual result reads as one smooth gradient of blur intensity, even though it's actually several discrete, uniformly-blurred layers stacked and faded into each other.

This is a genuinely clever workaround rather than an obvious one, and it's worth understanding why it took the design community a while to converge on it as the standard technique: the naive alternative — a single blurred layer with an opacity mask — doesn't actually vary blur intensity at all, it just varies how visible a uniformly-applied blur is. Fade a single blurred layer's opacity from 0 to 1 across a gradient and you get a blur that fades in and out of visibility, not one that ramps in *intensity*. The two look superficially similar in a quick glance but behave very differently once real content is scrolling underneath — an opacity-faded single blur has an abrupt, fixed blur "wall" wherever it becomes fully opaque, while the layered technique genuinely ramps continuously.

## Building It: The Layered Mask Technique

Here's a working implementation for a horizontal progressive blur (sharp on the left, increasingly blurred toward the right) — the pattern most commonly used behind a fixed nav bar over scrolling content.

```jsx
const LAYERS = [
  { blur: 2, maskStart: "0%", maskEnd: "40%" },
  { blur: 4, maskStart: "20%", maskEnd: "55%" },
  { blur: 8, maskStart: "40%", maskEnd: "70%" },
  { blur: 14, maskStart: "60%", maskEnd: "85%" },
  { blur: 24, maskStart: "80%", maskEnd: "100%" },
]

export function ProgressiveBlur(Component): ComponentType {
  return (props) => (
    <div style={{ position: "relative" }}>
      {LAYERS.map((layer, i) => (
        <div
          key={i}
          style={{
            position: "absolute",
            inset: 0,
            backdropFilter: `blur(${layer.blur}px)`,
            WebkitBackdropFilter: `blur(${layer.blur}px)`,
            maskImage: `linear-gradient(90deg, transparent ${layer.maskStart}, black ${layer.maskEnd}, black 100%)`,
            WebkitMaskImage: `linear-gradient(90deg, transparent ${layer.maskStart}, black ${layer.maskEnd}, black 100%)`,
          }}
        />
      ))}
      <Component {...props} />
    </div>
  )
}
```

Each layer is a full-area `backdrop-filter` blur, but its `mask-image` restricts where that specific blur amount is actually visible — layer 1 (barely blurred, 2px) is masked to fade in starting at 0% and be fully visible by 40%; layer 5 (heavily blurred, 24px) only becomes visible starting at 80%. Because the layers overlap in their transition zones and stack in increasing blur order, the combined effect at any given horizontal position is dominated by whichever layer's mask has faded in most fully there — producing a smooth-reading gradient of blur intensity even though each individual layer is internally uniform.

### Tuning Layer Count and Spacing

- **More layers = smoother gradient, more render cost.** 4-6 layers is the practical sweet spot — enough to avoid visible "stepping" between blur amounts, without excessive GPU overhead from too many stacked backdrop filters.
- **Overlapping mask ranges (as in the snippet, where each layer's range overlaps the next by roughly half) is what avoids visible seams.** If mask ranges don't overlap — layer 1 ending exactly where layer 2 begins — you'll see a harder transition line between blur amounts rather than a smooth ramp.
- **Non-linear blur progression often reads better than linear.** In the snippet, blur values jump 2 → 4 → 8 → 14 → 24 — roughly doubling rather than evenly spaced — because perceived blur intensity doesn't scale linearly with the numeric pixel value; equal visual steps typically need increasingly larger numeric jumps as blur increases.

## Vertical and Radial Variants

The same layered-mask technique works in any direction — swap the `linear-gradient(90deg, ...)` mask to `linear-gradient(180deg, ...)` for a vertical progressive blur (useful for a header blurring content as it scrolls beneath it), or to a `radial-gradient(...)` for a blur that intensifies outward from a center point, which suits a circular focal vignette effect around a hero subject.

## Where Progressive Blur Is Actually Used

- **Fixed navigation bars over scrolling content** — the single most common application. The blur is heaviest directly behind the nav's text/logo (for legibility against whatever scrolls beneath it) and fades to fully sharp a short distance below, rather than blurring the entire page uniformly.
- **Fading edges of horizontally scrollable content** — a card carousel or logo row where the edges progressively blur (rather than hard-cutting or fading to transparent) to suggest more content continues off-screen, a softer alternative to a flat opacity fade.
- **Depth-of-field style focal effects** on hero imagery, where a radial progressive blur draws the eye to a sharp center subject while the surrounding area softens, mimicking a shallow camera aperture.

It's overkill for anywhere a simple uniform blur or a plain opacity fade would achieve a similar practical result — reserve the layered technique for cases where the *gradient* quality specifically matters, like a nav bar that needs to stay legible against genuinely unpredictable, colorful content scrolling beneath it.

## Performance Notes

Each layer in the stack is its own `backdrop-filter`, and `backdrop-filter` is already one of the more GPU-intensive CSS properties on its own — stacking 4-6 of them compounds that cost meaningfully compared to a single blur layer. Keep the effect's total screen area small and purposeful (a nav bar strip a few hundred pixels tall, not a full-viewport background) and avoid animating the layered blur's size or position continuously, since that forces the browser to recompute the whole stack every frame rather than once. A progressive blur that's static (applied once, not animating) behind a fixed nav is cheap to keep running; one that's resizing or repositioning constantly is a different, more expensive proposition.

## Common Mistakes

- **Too few layers, producing visible banding.** If you can see distinct rings or steps in blur intensity rather than a smooth gradient, add more layers with more overlap between their mask ranges.
- **Linear blur value progression.** As covered above, equal numeric steps between layers (2, 4, 6, 8, 10) tend to look front-loaded and then flatten out, since perceived blur doesn't scale linearly — a roughly-doubling progression usually reads more evenly.
- **Applying the effect over a huge screen area.** The performance cost scales with the filtered area — keep it to the specific strip or edge that actually needs the gradient treatment.
- **Forgetting -webkit- prefixes.** Both `backdropFilter`/`WebkitBackdropFilter` and `maskImage`/`WebkitMaskImage` need their prefixed counterparts included for full cross-browser support, particularly Safari.
- **Testing only against a static screenshot rather than real scrolling content.** A progressive blur nav bar that looks perfect against one hero image can behave differently once a visitor scrolls past busier, higher-contrast content — always test against the actual range of content that will pass underneath the effect, not a single frame.

## A Simpler Alternative Worth Considering First

Before committing to the full 5-layer implementation, it's worth asking whether your actual goal is legibility (keeping nav text readable against whatever scrolls beneath it) or a specifically photographic depth-of-field look. If it's purely legibility, a single uniform `backdrop-filter` blur combined with a solid-color fill at low opacity — the standard glassmorphism nav pattern — often solves the practical problem with far less code and far less rendering cost, and most visitors won't consciously notice the difference between a uniform blur nav and a progressively-graduated one at a quick glance. Reach for the full layered technique specifically when the gradient quality itself is a deliberate part of your brand's visual language, not as a default first choice for every fixed nav bar.

## Pairing With Other Blur Effects

Progressive blur and glassmorphism share the same underlying `backdrop-filter` mechanic but solve different problems — glassmorphism is a uniform frosted panel with a defined edge, while progressive blur is specifically about a *gradient* of intensity across space, most often used for content legibility (a nav bar) rather than as a standalone decorative panel. Our [glassmorphism guide](/blog/glassmorphism-framer) covers the uniform-panel version in depth if that's closer to what you're after, and the two techniques can be combined — a glass nav panel with progressive blur fading into the scrolling content below it, rather than a hard-edged glass rectangle. If you'd rather not hand-build the layered mask stack, FramerHub's [component library](/components) has nav and header components with this treatment pre-built, available through the [Components plugin](/plugins/framer-components).

## FAQ

**What is progressive blur and how is it different from a normal blur?**
A normal blur applies one uniform blur amount across an entire area. Progressive blur increases gradually across a direction — sharp on one edge, increasingly blurred toward the other — which is closer to how depth-of-field works in photography and can't be achieved with a single backdrop-filter value.

**Why can't CSS animate a blur gradient directly?**
backdrop-filter and filter accept a single numeric blur value, not a gradient of values across space. To fake a spatial gradient of blur amounts, you stack multiple layers, each blurred by a different amount and masked to a different region, so the combined visual result reads as a smooth progression.

**How many blur layers do I need for a smooth progressive blur?**
4 to 6 layers is the practical range. Fewer than 4 and the transition between blur amounts can look visibly stepped; more than 6 adds rendering cost with diminishing visual improvement, since the difference between consecutive layers becomes imperceptible past a certain point.

**Where is progressive blur most commonly used?**
Fixed navigation bars over scrolling content (blurring only the area directly behind the nav, fading to fully sharp below it), and fading the edges of scrollable content or image galleries to signal more content continues off-screen.

**Is progressive blur expensive to render?**
More expensive than a single blur layer, since you're stacking multiple backdrop-filter layers rather than one, and each is a real GPU cost. Keep the effect's total area reasonably small (a nav bar strip, not a full-page overlay) and layer count in the 4-6 range.
