Material Fill Text
Large type filled with procedurally generated materials — wood grain, brushed metal, paper noise, marble and holo foil — cross-fading on autoplay or hover with a sweeping highlight, and no texture images loaded.
Present a headline as if it were made of material. The text itself is transparent; underneath sit five material layers generated live from CSS gradients and inline SVG feTurbulence noise — wood grain, brushed metal, paper, marble and holo foil — revealed only through the glyphs with background-clip: text. On each switch the new material cross-fades in while its texture glides forward a little, then a diagonal highlight sweeps across, like light passing over a real surface. It can autoplay, switch on hover, or follow a controlled material; change the seed for a different texture.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add material-fill-text.enPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<MaterialFillText/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
Installation
npx webberui@latest add https://webberui.com/r/material-fill-text.en.jsonOr, once registries are configured in components.json, install it as @webberui/material-fill-text.
Usage
import { MaterialFillText } from "@/components/ui/material-fill-text";
// Autoplay through all five materials
<MaterialFillText className="text-8xl font-black tracking-tight">
質地
</MaterialFillText>
// Advance on hover, using only three materials
<MaterialFillText mode="hover" materials={["metal", "foil", "wood"]}>
CRAFT
</MaterialFillText>
// Controlled: an external control decides the material
const [material, setMaterial] = React.useState<MaterialFillKind>("marble");
<MaterialFillText mode="manual" material={material} onMaterialChange={setMaterial}>
石與木
</MaterialFillText>Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | string | — | Text to fill with material (plain string; every material layer stacks an identical copy) |
materials | MaterialFillKind[] | ["wood", "metal", "paper", "marble", "foil"] | Materials in the rotation, in order; the first one is also where it stays under reduced motion |
material | MaterialFillKind | — | Current material in controlled mode; managed internally when omitted (uncontrolled) |
defaultMaterial | MaterialFillKind | materials[0] | Initial material in uncontrolled mode |
onMaterialChange | (material: MaterialFillKind) => void | — | Called when the material changes (fires for both autoplay and hover switching) |
mode | "auto" | "hover" | "manual" | "auto" | auto rotates on a timer, hover advances on pointer enter, manual follows the controlled material only |
interval | number | 2200 | Rotation interval in auto mode (ms); when omitted it reads --wb-material-fill-interval |
sheen | boolean | true | Sweep a diagonal highlight band across the text once on each switch (600ms) |
seed | number | 7 | Random seed for the procedural noise; change the number to get a different texture |
as | "h1" | "h2" | "p" | "span" | "h2" | Root element tag |
className | string | — | Passed to the root element; font size and weight come from here (default text-6xl font-black tracking-tight) |
MaterialFillKind
| Field | Type | Default | Description |
|---|---|---|---|
"wood" | string | — | Wood grain: layered brown stripes at slightly different angles plus stretched feTurbulence noise |
"metal" | string | — | Brushed metal: 1px greyscale hairlines and a diagonal highlight band |
"paper" | string | — | Paper: a paper-tone base with fine fractalNoise specks |
"marble" | string | — | Marble: turbulence noise turned into veins with feColorMatrix |
"foil" | string | — | Holo foil: a multicolour conic-gradient whose colours shift on hover |
How it works
- Structure: one transparent real-text layer handles layout, selection and screen readers; above it every material stacks its own copy of the text (
absolute, aligned,aria-hidden). The current material's layer is atopacity: 1, the rest at 0. - The pacing is overridable with CSS variables:
--wb-material-fill-duration(cross-fade, default450ms) and--wb-material-fill-interval(rotation interval, default2200ms; theintervalprop wins). - Noise is assembled as a
data:image/svg+xmlstring inside the component, with no external URLs; the string building is deterministic, so server and browser output match. - Every material has a light and a dark palette: light surfaces get the deeper versions (dark wood, dark steel, kraft paper, black marble), and dark mode (
dark:) switches to brightened versions so the text keeps enough contrast. - Rotation pauses automatically while the text is scrolled out of view; in controlled
automode the next switch is scheduled only after the parent writesmaterialback. - Material type is a display effect meant for large headings; keep body copy and small text in a regular text colour.
Accessibility
- The real text layer stays in the DOM, so it can be selected and copied and is read once by screen readers; every material layer and the sheen layer are
aria-hidden, so nothing is announced twice - In forced-colors mode (Windows High Contrast) the material layers are hidden and the real text falls back to the system text colour, so the content never disappears
- The switching is decorative and carries no information; if the material name matters, show it as text alongside, as the demo does
- When the user has enabled "reduce motion", it stays on the first material with no rotation and no sheen, and
mode="hover"does not switch either; controlledmanualmode still shows the requested material but switches instantly without a cross-fade
Launch Title Sequence
A launch-style sequence of title cards, each with its own entrance (blur-in, word stagger, punch, oversized pan, gradient keyword), background flips between cards and an optional HUD, played automatically or on scroll.
Bopomofo Ruby Text (React ruby typography component)
A React ruby typography component that annotates Chinese characters with Bopomofo (Zhuyin) or Hanyu Pinyin above them — switch between Bopomofo and Pinyin, highlight a character on hover, adjust the annotation size and spacing. Suited to teaching materials, dictionaries, and children's sites.