组件
渐进模糊 Progressive Blur
利用多层重叠梯度遮罩与 Backdrop Filter 实现边缘平滑衰减虚化、防止硬截断的视觉层次组件。
基础用法
在动态列表或长文本卡片底部叠加多层渐进模糊,使超出部分自然虚化并提供滚动心理暗示:
Loading…
安装与引入
通过 CLI 自动添加组件,或手动复制源码至项目中:
pnpm dlx @wui-design/cli@latest add @wui/progressive-blur安装基础依赖与动效库
pnpm add motion class-variance-authority clsx tailwind-merge复制组件源码到
components/ui/progressive-blur.tsx"use client"
import * as React from "react"
import { motion, type HTMLMotionProps } from "motion/react"
import { cn } from "@/lib/utils"
const gradientAngles = {
top: 0,
right: 90,
bottom: 180,
left: 270,
} as const
export interface ProgressiveBlurProps extends HTMLMotionProps<"div"> {
/** Edge that receives the strongest blur. @default "bottom" */
direction?: keyof typeof gradientAngles
/** Number of overlapping mask bands. Values below 2 are clamped. @default 8 */
blurLayers?: number
/** Blur added by each successive layer in pixels. @default 0.25 */
blurIntensity?: number
}
function ProgressiveBlur({
direction = "bottom",
blurLayers = 8,
blurIntensity = 0.25,
className,
...props
}: ProgressiveBlurProps) {
const layers = Math.max(Math.round(blurLayers), 2)
const segmentSize = 1 / (layers + 1)
const angle = gradientAngles[direction]
return (
<motion.div
aria-hidden="true"
data-slot="progressive-blur"
className={cn("pointer-events-none relative", className)}
{...props}
>
{Array.from({ length: layers }, (_, index) => {
const stops = [index, index + 1, index + 2, index + 3].map(
(position, stopIndex) =>
`rgba(0, 0, 0, ${stopIndex === 1 || stopIndex === 2 ? 1 : 0}) ${position * segmentSize * 100}%`
)
const maskImage = `linear-gradient(${angle}deg, ${stops.join(", ")})`
const blur = Math.max(0, index * blurIntensity)
return (
<div
key={index}
data-slot="progressive-blur-layer"
className="absolute inset-0 rounded-[inherit]"
style={{
maskImage,
WebkitMaskImage: maskImage,
backdropFilter: `blur(${blur}px)`,
WebkitBackdropFilter: `blur(${blur}px)`,
}}
/>
)
})}
</motion.div>
)
}
export { ProgressiveBlur, gradientAngles }
属性 Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| direction | "top" | "right" | "bottom" | "left" | "bottom" | 虚化衰减的主边缘方向(即模糊度最高的一侧)。 |
| blurLayers | number | 8 | 用于平滑过度的遮罩层分段数量(最小自动限制为 2)。 |
| blurIntensity | number | 0.25 | 每个分层逐级递增的模糊增量系数(像素)。数值越大,模糊总强度越高。 |
| className | string | — | 应用于外层定位容器的 CSS 类名(通常配置 absolute inset-x-0 bottom-0 等定位)。 |
| ...props | HTMLMotionProps<"div"> | — | 其余属性(如 style、initial / animate 等 Motion 动画属性)作用于外层容器,例如可对整个模糊层做淡入淡出。 |
事件 Events
该组件为纯展示型分层视觉遮罩层,自身不派发专用业务交互事件,默认标记 pointer-events: none 且不阻挡底层鼠标点击。
使用场景与设计规范
ProgressiveBlur 适用于截断列表提示、吸顶导航栏底部、图片渐隐遮罩:
- 告别生硬的纯色遮罩:传统的
bg-gradient-to-t from-background容易遮盖住文字的色彩,而渐进模糊(Backdrop Blur)则能保留底层色相同时让文本轮廓柔和化。 - 层数建议:通常 6 ~ 8 层可以在极佳的平滑度与 GPU 显存消耗之间取得完美平衡。
场景示例
上下方多方向虚化对比
在图片上叠加顶部或底部的渐进模糊,为标题与悬浮导航提供可读的底衬,而不必使用生硬的遮罩色块:
Loading…
无障碍与交互 Accessibility
- 点击穿透:容器默认携带
pointer-events-none,用户隔着模糊区域点击下方的链接或按钮依然能够精准响应。 - 无障碍树隐藏:默认设置
aria-hidden="true",屏幕阅读器不受任何视觉滤镜干扰。

