Fading Blur Mask
Hardware-accelerated linear gradient backdrop blur and surface tint overlay for seamless scrolling containers.
The Fading Blur Mask is a high-performance visual overlay primitive designed to eliminate harsh clipping boundaries in scrollable interfaces. It separates directional backdrop blur and Material Design 3 surface tint into two independent gradients, so blur and color recede together without visible banding or a cutoff.
Introduction
In modern expressive interfaces, content often scrolls continuously behind floating or pinned navigation elements. Standard translucent surfaces or abrupt solid borders can create sharp visual cuts that break immersion.
The MD3 Expressive Fading Blur Mask solves this by generating a continuous gradient falloff:
- At the outer boundary (e.g., top of the screen), the mask is opaque with full surface tinting and maximum backdrop blur.
- Toward the viewport center, both the backdrop blur and surface color smoothly attenuate to zero opacity, allowing underlying content to show cleanly.
It is built as both an independent primitive (<FadingBlurMask>) and as a built-in mixin (enableFadingBlur) for MD3 Expressive App Bars.
Anatomy
- Container Layer: Positioned absolutely (
absolute inset-0 z-0) withpointer-events: noneandaria-hidden="true"so it never intercepts user touch/clicks or pollutes screen reader trees. - Backdrop Blur Layer: One
backdrop-filteroverlay uses-webkit-mask-image/mask-imageto fade the requestedblurIntensitycontinuously. Blur automatically disables when reduced motion is preferred. - Tint Layer: A sibling overlay applies the color with the identical directional mask, avoiding the compositing artifacts caused by tinting the blur layer itself.
- Surface Color Tint: The tint follows the same fade as blur, so any MD3 token, CSS variable, or CSS color blends without a hard cutoff.
- Content Slot: Supports optional child elements rendered within the mask coordinate system.
Variants
Directional Presets
The mask supports three directional modes depending on where content enters or exits the scroll viewport:
- Top (
direction="top"): Opaque at the top, fading to transparent downward. Ideal for Top App Bars, collapsible headers, and search bars. - Bottom (
direction="bottom"): Opaque at the bottom, fading to transparent upward. Designed for Bottom App Bars, docked toolbars, and sticky footers. - Both (
direction="both"): Fades simultaneously at both top and bottom edges. Suitable for modal dialog viewports, inline carousels, or centered scroll areas.
App Bar Integration
The fading blur effect is built directly into all MD3 Expressive App Bar components via the enableFadingBlur mixin prop.
Features
Hardware Acceleration & Mask Gradients
Two lightweight, non-interactive sibling layers share one directional gradient:
- Top: Maximum blur and tint at the top edge, then a continuous fade toward the content.
- Bottom: The equivalent transition from the bottom edge upward.
- Both: Independent mirrored transitions at both edges, with a clear center.
Accessibility & Reduced Motion
The component integrates with useReducedMotion() from motion/react. When a user enables system-level prefers-reduced-motion, the backdrop blur intensity automatically drops to 0px to conserve GPU resources and reduce visual vestibulary strain.
Flexible Dimensions & Colors
You can customize:
blurIntensity: Default12px, customizable up to32pxor higher.blurHeight: Supports CSS strings (e.g."64px","100%") or numeric pixel values.color: Defaults tovar(--md-sys-color-surface), but accepts any color string (e.g. surface containers or translucent tinted alphas).
Usage
Standalone Usage
import { FadingBlurMask } from "@bug-on/m3-expressive/layout";
// Alternatively import from subpaths:
// import { FadingBlurMask } from "@bug-on/m3-expressive/layout";
// import { FadingBlurMask } from "@bug-on/m3-expressive/navigation";
export function ScrollContainerWithMask() {
return (
<div className="relative h-96 w-full overflow-hidden rounded-2xl border">
{/* Positioned inside a relative container */}
<FadingBlurMask
direction="top"
blurIntensity={16}
blurHeight={72}
color="var(--md-sys-color-surface-container)"
/>
{/* Scrollable content */}
<div className="h-full overflow-y-auto p-4 space-y-3">
{/* items */}
</div>
</div>
);
}
With App Bars
import { SmallAppBar } from "@bug-on/m3-expressive/navigation";
<SmallAppBar
title="Collapsible Header"
enableFadingBlur
blurIntensity={16}
blurHeight={64}
fadingBlurColor="var(--md-sys-color-surface-container)"
/>
Best Practices
Do
- Use
direction="top"for pinned top navigation anddirection="bottom"for docked bottom toolbars. - Keep
pointerEvents: noneactive so underlying interactive elements remain clickable. - Maintain contrast with the default MD3 surface token
var(--md-sys-color-surface)so the blur integrates with dark mode seamlessly. - Keep the blur radius between
12pxand24pxfor optimal performance and legibility.
Don't
- Don't remove
aria-hidden="true", as the blur mask is purely decorative. - Don't use excessively large blur radii (> 48px) on low-end mobile devices to avoid GPU fill-rate throttling.
- Don't apply the mask inside a container without
position: relativeoroverflow: hidden.
Design Tokens
Color System
The mask utilizes semantic MD3 color tokens for natural background matching:
| Token | CSS Variable | Purpose |
|---|---|---|
| Surface | --md-sys-color-surface | Default surface tint background |
| Surface Container | --md-sys-color-surface-container | Card and modal dialog backdrop tint |
| Surface Container Low | --md-sys-color-surface-container-low | Flat surface overlays |
Blur & Motion Tokens
| Property | Default Value | Recommended Range |
|---|---|---|
| Default Blur | 12px | 8px – 24px |
| App Bar Preset | 16px | 12px – 20px |
| Reduced Motion Blur | 0px | Automatically applied |
Accessibility
- Decorative Element: Built with
aria-hidden="true", preventing screen readers from announcing empty presentation elements. - Event Transparency: Has
pointer-events: none, allowing touch, click, and scroll events to pass directly through to underlying elements. - Prefers Reduced Motion: Automatically zeroes the backdrop blur when the user has requested reduced motion.
API Reference
FadingBlurMask
The primary primitive component.
| Prop | Type | Default | Description |
|---|---|---|---|
direction | "top" | "bottom" | "both" | "top" | Gradient fade direction. |
blurIntensity | number | 12 | Backdrop blur radius in pixels. |
blurHeight | number | string | "100%" | Height of the fade mask container or gradient zone. |
color | string | var(--md-sys-color-surface) | Tint color that fades continuously with the blur. |
className | string | undefined | Additional CSS class names. |
style | React.CSSProperties | undefined | Custom inline styles. |
children | ReactNode | undefined | Optional children rendered inside the blur mask container. |
FadingBlurProps
Mixin interface integrated into MD3 Expressive App Bars (SmallAppBar, MediumFlexibleAppBar, LargeFlexibleAppBar, BottomAppBar).
| Prop | Type | Default | Description |
|---|---|---|---|
enableFadingBlur | boolean | false | Enables smooth fading edge and backdrop blur effect. |
blurIntensity | number | 12 | Custom blur intensity in pixels when active. |
blurHeight | number | string | undefined | Custom blur height. Defaults to container height. |
fadingBlurColor | string | App Bar container color | Custom tint color that fades continuously with the blur. |
FadingBlurDirection
Union type representing allowed gradient directions:
type FadingBlurDirection = "top" | "bottom" | "both";