Edge Veil Blur
A veil of progressive blur pinned to one edge of a scroll container: a masked backdrop-filter band fades from full blur at the edge to nothing over the content, with an optional surface tint riding the same gradient so rows dissolve instead of hitting a hard clip line. Four sides, tint color and strength all configurable.
Micro InteractionReactTailwind CSS
CSSTailwind
Manual
Create a file and paste the following code into it.
edge-veil-blur.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
"use client";
import { type CSSProperties, type HTMLAttributes } from "react";
import { cn } from "@/lib/cn";
/* ------------------------------------------------------------------ */
/* EdgeVeilBlur */
/* ------------------------------------------------------------------ */
export type VeilSide = "top" | "bottom" | "left" | "right";
interface EdgeVeilBlurProps extends HTMLAttributes<HTMLDivElement> {
/** Edge the blur is strongest at [Optional, default: "bottom"] */
side?: VeilSide;
/** Backdrop blur in px [Optional, default: 4] */
strength?: number;
/** Thickness of the veiled band [Optional, default: "160px"] */
size?: string | number;
/** Fade a surface tint alongside the blur [Optional, default: true] */
tint?: boolean;
/** Tint color (defaults to the page surface in both modes) [Optional] */
tintColor?: string;
/** Tint opacity at the solid edge 0-1 [Optional, default: 1] */
tintStrength?: number;
}
const IS_HORIZONTAL: Record<VeilSide, boolean> = {
top: false,
bottom: false,
left: true,
right: true,
};
/* The gradient runs FROM the edge (opaque) TO the content (transparent). */
const FADE_DIR: Record<VeilSide, string> = {
top: "to bottom",
bottom: "to top",
left: "to right",
right: "to left",
};
const POSITION: Record<VeilSide, CSSProperties> = {
top: { top: 0, left: 0 },
bottom: { bottom: 0, left: 0 },
left: { top: 0, left: 0 },
right: { top: 0, right: 0 },
};
/**
* A veil of progressive blur pinned to one edge of a scroll container:
* a masked backdrop-filter band that fades from full blur at the edge to
* nothing over the content, with an optional surface tint riding the same
* gradient so text dissolves instead of hitting a hard clip line.
* @param {VeilSide} side - Strongest edge [Optional, default: "bottom"]
* @param {number} strength - Backdrop blur px [Optional, default: 4]
*/
export function EdgeVeilBlur({
side = "bottom",
strength = 4,
size = "160px",
tint = true,
tintColor = "light-dark(#ffffff, #09090b)",
tintStrength = 1,
className,
style,
...props
}: EdgeVeilBlurProps) {
const isHorizontal = IS_HORIZONTAL[side];
const fadeDir = FADE_DIR[side];
const sizeValue = typeof size === "number" ? `${size}px` : size;
const sizeStyle: CSSProperties = isHorizontal
? { width: sizeValue, height: "100%" }
: { height: sizeValue, width: "100%" };
const maskImage = `linear-gradient(${fadeDir}, black 50%, transparent 100%)`;
const background = tint
? `linear-gradient(${fadeDir}, color-mix(in oklch, ${tintColor} ${Math.round(
tintStrength * 100,
)}%, transparent) 0%, transparent 100%)`
: undefined;
return (
<div
aria-hidden="true"
className={cn("pointer-events-none absolute z-10", className)}
style={{
...sizeStyle,
...POSITION[side],
background,
maskImage,
WebkitMaskImage: maskImage,
backdropFilter: `blur(${strength}px)`,
WebkitBackdropFilter: `blur(${strength}px)`,
willChange: "backdrop-filter",
...style,
}}
{...props}
/>
);
}
Update the import paths to match your project setup.
Similar components
Install via CLI
Resource details
PublishedJuly 17, 2026
CategoryMicro Interaction
ReactTailwind CSS
Install via CLI
Resource details
PublishedJuly 17, 2026
CategoryMicro Interaction
ReactTailwind CSS