---
title: "GradualBlur"
description: "A layered blur that fades in from the edge of a container or page."
category: Effects
status: beta
since: 0.3.4
tags: [blur, edge-fade, overlay, backdrop-filter]
syncStatus: reviewed
verified: true
---

## Usage

### Basic
It sits on the parent's bottom edge by default; `strength`, `divCount`, and `curve` set how strong the blur is and how it ramps.
:::TuffDemoWrapper{demo="GradualBlurGradualBlurDemo" code-lang="vue"}
---
code: |
  <template>
    <section style="position: relative; height: 320px; overflow: hidden;">
      <div style="height: 100%; overflow-y: auto;">
        <!-- long content -->
      </div>
      <TxGradualBlur
        target="parent"
        position="bottom"
        height="6rem"
        :strength="2"
        :div-count="5"
        curve="bezier"
        :exponential="true"
      />
    </section>
  </template>
---
:::

### Positions
`position` picks the edge; on the left and right, `width` sets the thickness.
:::TuffDemoWrapper{demo="GradualBlurPositionsDemo" code-lang="vue"}
---
code: |
  <template>
    <section class="pane">
      <!-- scrollable content -->
      <TxGradualBlur position="top" height="4.5rem" :strength="2.2" :div-count="6" curve="ease-out" />
    </section>
    <section class="pane">
      <TxGradualBlur position="bottom" height="5rem" :strength="2.2" :div-count="6" curve="ease-out" />
    </section>
    <section class="pane">
      <TxGradualBlur position="left" width="5rem" :strength="2.5" :div-count="7" curve="bezier" />
    </section>
    <section class="pane">
      <TxGradualBlur position="right" width="5rem" :strength="2.5" :div-count="7" curve="bezier" />
    </section>
  </template>
---
:::

### Presets
:::TuffDemoWrapper{demo="GradualBlurPresetsDemo" code-lang="vue"}
---
code: |
  <template>
    <section class="pane"><TxGradualBlur preset="subtle" /></section>
    <section class="pane"><TxGradualBlur preset="intense" /></section>
    <section class="pane"><TxGradualBlur preset="smooth" /></section>
    <section class="pane"><TxGradualBlur preset="sharp" /></section>
    <section class="pane"><TxGradualBlur preset="header" /></section>
    <section class="pane"><TxGradualBlur preset="footer" /></section>
  </template>
---
:::

### Hover Intensity
:::TuffDemoWrapper{demo="GradualBlurHoverIntensityDemo" code-lang="vue"}
---
code: |
  <template>
    <TxGradualBlur
      position="bottom"
      height="6rem"
      :strength="2"
      :div-count="6"
      curve="bezier"
      :hover-intensity="1.8"
      :exponential="true"
    />
  </template>
---
:::

### Reveal on Scroll
:::TuffDemoWrapper{demo="GradualBlurAnimatedScrollDemo" code-lang="vue"}
---
code: |
  <template>
    <TxGradualBlur
      position="bottom"
      height="6.5rem"
      :strength="2.4"
      animated="scroll"
      duration="0.35s"
      :on-animation-complete="onRevealed"
    />
  </template>
---
:::

### Page Target
:::TuffDemoWrapper{demo="GradualBlurTargetPageDemo" code-lang="vue"}
---
code: |
  <template>
    <TxGradualBlur
      target="page"
      preset="page-footer"
      :div-count="8"
      :exponential="true"
      :strength="2.5"
      :z-index="9999"
      :style="{ left: 0, right: 0 }"
    />
  </template>
---
:::

### Responsive Sizes
:::TuffDemoWrapper{demo="GradualBlurResponsiveSizesDemo" code-lang="vue"}
---
code: |
  <template>
    <TxGradualBlur
      position="bottom"
      :strength="2"
      responsive
      height="6rem"
      mobile-height="4rem"
      tablet-height="5rem"
      desktop-height="7rem"
    />
  </template>
---
:::

### Best Practices

- For card-local fades, keep the parent `position: relative` and `overflow: hidden`; use `target="page"` only for fixed page chrome.
- Raise `divCount` for a smoother ramp before tuning `strength`; every layer adds backdrop-filter work.
- Start common headers and footers from a `preset` and override one or two props.
- Don't set `hoverIntensity` when interactive controls sit under the overlay.
- Check contrast in both themes; the blur depends on the content behind it.

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `position` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'bottom'` | Edge to attach to; also sets the mask gradient's direction. |
| `strength` | `number` | `2` | Multiplier for each layer's blur radius. |
| `height` | `string` | `'6rem'` | Thickness on top and bottom; left and right use it when `width` is unset. |
| `width` | `string` | - | Overlay width; `100%` on top and bottom, `height` on left and right. |
| `divCount` | `number` | `5` | Number of layers; floored, minimum 1. |
| `exponential` | `boolean` | `false` | Grows the blur exponentially instead of linearly. |
| `curve` | `'linear' \| 'bezier' \| 'ease-in' \| 'ease-out' \| 'ease-in-out'` | `'linear'` | How blur progress is spread across layers. |
| `opacity` | `number` | `1` | Opacity of every layer. |
| `animated` | `boolean \| 'scroll'` | `false` | Enables opacity and blur transitions; `'scroll'` fades in only once in view. |
| `duration` | `string` | `'0.3s'` | Transition duration. |
| `easing` | `string` | `'ease-out'` | Transition easing. |
| `zIndex` | `number` | `1000` | Base z-index; `target="page"` adds `100`. |
| `target` | `'parent' \| 'page'` | `'parent'` | `parent` is absolute inside the parent; `page` is fixed to the viewport. |
| `hoverIntensity` | `number` | - | Multiplies `strength` while hovered and makes the overlay take pointer events. |
| `responsive` | `boolean` | `false` | Switches sizes by viewport width, with a debounced resize listener. |
| `mobileHeight` | `string` | - | Height at viewports `<= 480px` when `responsive`. |
| `tabletHeight` | `string` | - | Height at viewports `<= 768px` when `responsive`. |
| `desktopHeight` | `string` | - | Height at viewports `<= 1024px` when `responsive`. |
| `mobileWidth` | `string` | - | Width at viewports `<= 480px` when `responsive`. |
| `tabletWidth` | `string` | - | Width at viewports `<= 768px` when `responsive`. |
| `desktopWidth` | `string` | - | Width at viewports `<= 1024px` when `responsive`. |
| `preset` | `'top' \| 'bottom' \| 'left' \| 'right' \| 'subtle' \| 'intense' \| 'smooth' \| 'sharp' \| 'header' \| 'footer' \| 'sidebar' \| 'page-header' \| 'page-footer'` | - | Applies a preset first; props you pass still override it. |
| `gpuOptimized` | `boolean` | `false` | Adds `will-change: backdrop-filter, opacity` and `translateZ(0)`. |
| `onAnimationComplete` | `() => void` | - | Called once an `animated="scroll"` overlay shows and `duration` elapses. |
| `className` | `string` | `''` | Extra class on the root. |
| `style` | `CSSProperties` | `{}` | Root inline style, merged after the generated positioning. |

### Slots

| Slot | Description |
|------|-------------|
| `default` | Optional content rendered above the blur layers. |

## Overview

- The overlay is decorative and `pointer-events: none` by default; it takes pointer events only with `hoverIntensity`.
- With `target="page"`, top and bottom overlays span the full viewport width by default.
- `animated="scroll"` starts hidden, watches the root with `IntersectionObserver`, and fades in once visible.

## Technologies

- Each layer is a `backdrop-filter` blur limited by its own `mask-image` band; blur values rise along `curve` and stack into one continuous fade.
- Source: `packages/tuffex/packages/components/src/gradual-blur/`.

<TuffDocSourceLink />
