Skip to component
GGamma

Gradual blur

A scroll region whose content dissolves into a blur at the edges, built from masked backdrop-filter layers.

New

Fade edges

Scroll the specimen. The top edge fades the content in and the bottom edge dissolves it into a blur, one slice at a time.

Section 01, 2 columns

Reading the specimen

Type is read in long measures, so the specimen sets a narrow column and lets the line breathe. The blur at the edges should make the top of the next section arrive rather than appear.

Section 02, 3 columns

Weight and measure

Four weights share one rhythm. The optical sizes step down through the set, and the tracking opens as the measure gets smaller.

Section 03, 1 column

A note on colour

The surface tone carries the specimen and the ink does the reading. Nothing here needs a border to be legible, so the space between sections is the only line on the page.

Section 04, 2 columns

Spacing at the baseline

An 8pt grid with a 1.5 line height. The spacing between sections is double the spacing inside one, and the eye uses that to find the joins.

Section 05, 3 columns

The last measure

The final section is the one that scrolls under the blur, so it is the one worth reading twice. Everything above it stays sharp until the ramp reaches it.

The specimen starts sharp at the top edge.

Live previewUse keyboard to interact

Implementation

1"use client";2 3import {4  useMemo,5  type CSSProperties,6  type HTMLAttributes,7  type ReactNode,8  type Ref,9} from "react";10 11export type GradualBlurProps = Omit<12  HTMLAttributes<HTMLDivElement>,13  "children"14> & {15  /** The scrollable content. */16  children: ReactNode;17  /** Accessible name for the scroll region. */18  label?: string;19  /** The strongest blur in the ramp, in pixels. */20  blur?: number;21  /** How many slices the ramp is built from. */22  layers?: number;23  /** The height of the edge band, in pixels. */24  bandSize?: number;25  /** A ref to the scrollable viewport, for callers that drive the scroll. */26  viewportRef?: Ref<HTMLDivElement>;27  /** Additional class name for the root. */28  className?: string;