Components/GradualBlur
Universal Component

GradualBlur

Layered backdrop blur overlay for soft edge fades, presets, hover intensity, and responsive dimensions.

This page was migrated by AI, please review carefully

Migration is complete, but please validate against source code and manual review.

GradualBlur

TxGradualBlur stacks masked backdrop-filter layers to create a directional edge fade. Presets provide common edge strengths, while explicit props override preset values for precise parent or page overlays.

Basic Usage

GradualBlur

Demo will load when visible.
<template>
  <section style="position: relative; height: 320px; overflow: hidden; border-radius: 12px; border: 1px solid var(--tx-border-color);">
    <div style="height: 100%; overflow-y: auto; padding: 2rem 1rem; background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0));">
      <div style="font-weight: 600; margin-bottom: 8px;">
        Scrollable Content
      </div>
      <div style="color: var(--tx-text-color-secondary); line-height: 1.7;">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
        <div style="height: 16px;" />
        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
        <div style="height: 16px;" />
        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
        <div style="height: 16px;" />
        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
        <div style="height: 16px;" />
        More lines. More lines. More lines. More lines. More lines.
        <div style="height: 120px;" />
        Bottom.
      </div>
    </div>

    <TxGradualBlur
      target="parent"
      position="bottom"
      height="6rem"
      :strength="2"
      :div-count="5"
      curve="bezier"
      :exponential="true"
      :opacity="1"
    />
  </section>
</template>

Direction (Top / Bottom / Left / Right)

Positions

Demo will load when visible.
<template>
  <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; width: 620px;">
    <section style="position: relative; height: 220px; overflow: hidden; border-radius: 16px; border: 1px solid var(--tx-border-color); background: linear-gradient(180deg, rgba(125,211,252,.24), rgba(255,255,255,0));">
      <div style="height: 100%; overflow-y: auto; padding: 1.4rem 1.2rem; display: flex; flex-direction: column; gap: 12px;">
        <div style="display: flex; justify-content: space-between; align-items: center; font-weight: 600;">
          <span>Top fade</span>
          <span style="font-size: 20px;">↑</span>
        </div>
        <p style="color: var(--tx-text-color-secondary); line-height: 1.6; margin: 0;">
          Headline content stays sharp,Text。
        </p>
        <div style="height: 160px;" />
        <p style="color: var(--tx-text-color-secondary); margin: 0;">
          End.
        </p>
      </div>
      <TxGradualBlur position="top" height="4.5rem" :strength="2.2" :div-count="6" curve="ease-out" />
    </section>

    <section style="position: relative; height: 220px; overflow: hidden; border-radius: 16px; border: 1px solid var(--tx-border-color); background: linear-gradient(180deg, rgba(168,85,247,.08), rgba(255,255,255,0));">
      <div style="height: 100%; overflow-y: auto; padding: 1.4rem 1.2rem; display: flex; flex-direction: column; gap: 12px;">
        <div style="display: flex; justify-content: space-between; align-items: center; font-weight: 600;">
          <span>Bottom fade</span>
          <span style="font-size: 20px;">↓</span>
        </div>
        <p style="color: var(--tx-text-color-secondary); line-height: 1.6; margin: 0;">
          Text,Text CTA Text。
        </p>
        <div style="height: 200px;" />
        <p style="color: var(--tx-text-color-secondary); margin: 0;">
          End.
        </p>
      </div>
      <TxGradualBlur position="bottom" height="5rem" :strength="2.2" :div-count="6" curve="ease-out" />
    </section>

    <section style="position: relative; height: 200px; overflow: hidden; border-radius: 16px; border: 1px solid var(--tx-border-color); background: linear-gradient(90deg, rgba(14,165,233,.06), rgba(255,255,255,0));">
      <div style="height: 100%; overflow-y: auto; padding: 1.2rem; display: flex; flex-direction: column; gap: 10px;">
        <div style="display: flex; justify-content: space-between; align-items: center; font-weight: 600;">
          <span>Left pane</span>
          <span style="font-size: 20px;">←</span>
        </div>
        <p style="color: var(--tx-text-color-secondary); line-height: 1.5; margin: 0;">
          SidebarText + IconText,TexthandleText。
        </p>
        <div style="flex: 1; display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;">
          <div style="height: 48px; border-radius: 8px; background: rgba(125,211,252,.35);" />
          <div style="height: 48px; border-radius: 8px; background: rgba(59,130,246,.25);" />
          <div style="height: 48px; border-radius: 8px; background: rgba(37,99,235,.25);" />
        </div>
      </div>
      <TxGradualBlur position="left" width="5rem" :strength="2.5" :div-count="7" curve="bezier" />
    </section>

    <section style="position: relative; height: 200px; overflow: hidden; border-radius: 16px; border: 1px solid var(--tx-border-color); background: linear-gradient(90deg, rgba(236,72,153,.08), rgba(255,255,255,0));">
      <div style="height: 100%; overflow-y: auto; padding: 1.2rem; display: flex; flex-direction: column; gap: 10px;">
        <div style="display: flex; justify-content: space-between; align-items: center; font-weight: 600;">
          <span>Right pane</span>
          <span style="font-size: 20px;">→</span>
        </div>
        <p style="color: var(--tx-text-color-secondary); line-height: 1.5; margin: 0;">
          Text,Text。
        </p>
        <div style="flex: 1; display: flex; gap: 6px;">
          <div style="flex: 1; border-radius: 10px; background: rgba(248,113,113,.15);" />
          <div style="flex: 1; border-radius: 10px; background: rgba(251,146,60,.15);" />
        </div>
      </div>
      <TxGradualBlur position="right" width="5rem" :strength="2.5" :div-count="7" curve="bezier" />
    </section>
  </div>
</template>

Preset

Presets

Demo will load when visible.
<template>
  <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; width: 640px;">
    <section style="position: relative; height: 140px; overflow: hidden; border-radius: 12px; border: 1px solid var(--tx-border-color);">
      <div style="height: 100%; overflow-y: auto; padding: 1rem;">
        <div style="font-weight: 600;">
          subtle
        </div>
        <div style="height: 120px;" />
      </div>
      <TxGradualBlur preset="subtle" />
    </section>

    <section style="position: relative; height: 140px; overflow: hidden; border-radius: 12px; border: 1px solid var(--tx-border-color);">
      <div style="height: 100%; overflow-y: auto; padding: 1rem;">
        <div style="font-weight: 600;">
          intense
        </div>
        <div style="height: 120px;" />
      </div>
      <TxGradualBlur preset="intense" />
    </section>

    <section style="position: relative; height: 140px; overflow: hidden; border-radius: 12px; border: 1px solid var(--tx-border-color);">
      <div style="height: 100%; overflow-y: auto; padding: 1rem;">
        <div style="font-weight: 600;">
          smooth
        </div>
        <div style="height: 120px;" />
      </div>
      <TxGradualBlur preset="smooth" />
    </section>

    <section style="position: relative; height: 140px; overflow: hidden; border-radius: 12px; border: 1px solid var(--tx-border-color);">
      <div style="height: 100%; overflow-y: auto; padding: 1rem;">
        <div style="font-weight: 600;">
          sharp
        </div>
        <div style="height: 120px;" />
      </div>
      <TxGradualBlur preset="sharp" />
    </section>

    <section style="position: relative; height: 140px; overflow: hidden; border-radius: 12px; border: 1px solid var(--tx-border-color);">
      <div style="height: 100%; overflow-y: auto; padding: 1rem;">
        <div style="font-weight: 600;">
          header
        </div>
        <div style="height: 120px;" />
      </div>
      <TxGradualBlur preset="header" />
    </section>

    <section style="position: relative; height: 140px; overflow: hidden; border-radius: 12px; border: 1px solid var(--tx-border-color);">
      <div style="height: 100%; overflow-y: auto; padding: 1rem;">
        <div style="font-weight: 600;">
          footer
        </div>
        <div style="height: 120px;" />
      </div>
      <TxGradualBlur preset="footer" />
    </section>
  </div>
</template>

Hover Intensity Boost (hoverIntensity)

HoverIntensity

Demo will load when visible.
<template>
  <section style="position: relative; height: 220px; overflow: hidden; border-radius: 12px; border: 1px solid var(--tx-border-color);">
    <div style="height: 100%; overflow-y: auto; padding: 1.25rem 1rem;">
      <div style="font-weight: 600; margin-bottom: 8px;">
        Hover the blurred area
      </div>
      <div style="color: var(--tx-text-color-secondary); line-height: 1.7;">
        When hoverIntensity is provided, the blur overlay will accept pointer events.
        <div style="height: 220px;" />
        End.
      </div>
    </div>

    <TxGradualBlur
      position="bottom"
      height="6rem"
      :strength="2"
      :div-count="6"
      curve="bezier"
      :hover-intensity="1.8"
      :exponential="true"
    />
  </section>
</template>

Trigger on Viewport (animated="scroll")

Animated scroll

Demo will load when visible.
<script setup lang="ts">
import GradualBlurAnimatedDemo from './GradualBlurAnimatedDemo.vue'
</script>

<template>
  <GradualBlurAnimatedDemo />
</template>

Page Target (target="page")

Target page

Demo will load when visible.
<template>
  <div style="position: relative; height: 220px; border-radius: 12px; border: 1px solid var(--tx-border-color); overflow: hidden;">
    <div style="padding: 1rem; color: var(--tx-text-color-secondary);">
      This box only exists to show a fixed blur overlay.
    </div>

    <TxGradualBlur
      target="page"
      preset="page-footer"
      :div-count="8"
      :exponential="true"
      :opacity="1"
      :strength="2.5"
      :z-index="9999"
      :style="{ left: 0, right: 0 }"
    />
  </div>
</template>

Responsive Sizes (responsive)

Responsive sizes

Demo will load when visible.
<template>
  <section style="position: relative; height: 220px; overflow: hidden; border-radius: 12px; border: 1px solid var(--tx-border-color);">
    <div style="height: 100%; overflow-y: auto; padding: 1.25rem 1rem;">
      <div style="font-weight: 600; margin-bottom: 8px;">
        Resize window to see height changes
      </div>
      <div style="color: var(--tx-text-color-secondary); line-height: 1.7;">
        desktop/tablet/mobile heights can be configured.
        <div style="height: 220px;" />
        End.
      </div>
    </div>

    <TxGradualBlur
      position="bottom"
      :strength="2"
      responsive
      height="6rem"
      mobile-height="4rem"
      tablet-height="5rem"
      desktop-height="7rem"
    />
  </section>
</template>

API

Props

PropTypeDefaultDescription
position'top' | 'bottom' | 'left' | 'right''bottom'Edge where the blur overlay is anchored and the mask gradient direction is derived.
strengthnumber2Multiplier used to calculate each layer's blur radius.
heightstring'6rem'Overlay thickness for top/bottom positions; also used as fallback width for left/right positions.
widthstring-Overlay width. Top/bottom default to 100%; left/right fall back to height when omitted.
divCountnumber5Number of masked blur layers; values below 1 are clamped to one layer.
exponentialbooleanfalseUses exponential blur scaling instead of linear per-layer blur scaling.
curve'linear' | 'bezier' | 'ease-in' | 'ease-out' | 'ease-in-out''linear'Curve used to distribute blur progression across layers.
opacitynumber1Opacity applied to every blur layer.
animatedboolean | 'scroll'falseEnables opacity/filter transitions; 'scroll' waits for intersection visibility before fading in.
durationstring'0.3s'CSS duration used by opacity and blur transitions.
easingstring'ease-out'CSS easing used by opacity and blur transitions.
zIndexnumber1000Base z-index. Page-target overlays add 100 to this value.
target'parent' | 'page''parent'parent renders absolute positioning; page renders fixed positioning.
hoverIntensitynumber-Multiplies blur strength while hovered and enables pointer events on the overlay.
responsivebooleanfalseEnables viewport-width based height/width overrides and installs a debounced resize listener.
mobileHeightstring-Height used at viewport widths <= 480px when responsive is enabled.
tabletHeightstring-Height used at viewport widths <= 768px when responsive is enabled.
desktopHeightstring-Height used at viewport widths <= 1024px when responsive is enabled.
mobileWidthstring-Width used at viewport widths <= 480px when responsive is enabled.
tabletWidthstring-Width used at viewport widths <= 768px when responsive is enabled.
desktopWidthstring-Width used at viewport widths <= 1024px when responsive is enabled.
preset'top' | 'bottom' | 'left' | 'right' | 'subtle' | 'intense' | 'smooth' | 'sharp' | 'header' | 'footer' | 'sidebar' | 'page-header' | 'page-footer'-Applies a preset config first; explicitly provided props still override preset values.
gpuOptimizedbooleanfalseAdds will-change: backdrop-filter, opacity and translateZ(0) to the overlay.
onAnimationComplete() => void-Called after a scroll-triggered overlay becomes visible and the configured duration elapses.
classNamestring''Extra class appended to the root element.
styleCSSProperties{}Extra inline style merged into the root style after generated positioning styles.

Usage Tips

  • Container positioning When target="parent", set parent position: relative and use overflow: hidden to clip edges.
  • Browser support Depends on backdrop-filter; rendering may vary across engines.