shadcn.io is not affiliated with official shadcn/ui
Backgrounds
ProInk Background for React
Ink blooming in clear water: soft plumes unfurl, curl into veils and filaments, sink and thin out while new ones bloom elsewhere, at three depths. For React with Base UI, when an editorial hero, a studio or a calm landing page needs slow, fluid motion behind its copy.
Ink blooms in clear water behind your content: soft plumes unfurl from points across the box, curl into veils and fine filaments as they spread, sink a little and thin out, while new ones bloom somewhere else. They sit at three depths, so the far ones are larger, softer, fainter and slower, and about half the box is always inked. Each plume is one element in its ink's colour, masked by an image the browser draws once from an SVG filter: noise that billows a soft mass and then warps itself, which folds it into the swirls of real ink; the far ones are soft, out-of-focus lumps. CSS keyframes then grow, turn, move and fade each plume, three blooms in three places per loop, so no script runs and nothing repaints. It's indigo ink in a light page and luminous cyan and violet on a dark one.
Use it behind an editorial hero, a studio's landing page or a quote. For soft pigment washes that dry on paper, use Watercolor; for rising smoke, Smoke; for water rings where drops land, Drops; for blobs that fuse instead of spreading, Metaballs.
Installation
Usage
import { Ink } from "@/components/ui/ink";<Ink className="flex min-h-[32rem] items-center justify-center">
<h1 className="font-serif text-5xl">The first stroke</h1>
</Ink>Ink is a container: whatever you put inside sits on top of the ink, in normal flow. It fills its own box, so give it a height or content. The water is whatever is behind it, your page's background by default; for a backdrop behind the whole page, render it empty with className="fixed inset-0 -z-10".
Demos
Sumi and vermilion
colors takes any CSS colours, theme variables too, and plumes take turns with them: here your text colour, twice, and a vermilion red, like brush ink with a seal.
In a card
A card with count={5} plumes, intensity="subtle" for thinner ink and speed={0.6} for slower blooms, quiet enough to sit behind body copy.
Accessibility
The ink is decoration: it's hidden from assistive tech and lets every click through to your content. With reduced motion the plumes hold still, mid-bloom, so a calm still of ink in water stays. Nothing flashes: each bloom takes 14 to 31 seconds to unfurl and fade.
Put copy over it in your foreground colour (text-foreground). At the default intensity the ink is thinned so text keeps at least 4.5:1 over a hero's copy area at the densest moment we measured (about 5:1 on a light page, 5.5:1 on a dark one, where the ink is thinner because light ink glows). intensity="strong" darkens every plume by about a third, so use it for headlines; for small body copy, use intensity="subtle" or set it on a surface.
FAQ
How are the plumes drawn?
Each plume is one element in its ink's colour, masked by an SVG image: one noise billows a soft mass into lobes, then warps itself (domain warping), which folds it into curls and veils. One noise per image keeps the first paint quick even where the browser runs filters on the processor. The browser draws that image once; after that CSS only grows, turns, moves and fades the plume with scale, rotate, translate and opacity, which the browser composites without repainting.
What are the three depths?
A third of the plumes are far back: larger, drawn as soft, out-of-focus lumps, fainter and slower. The rest are near the glass, sharper and denser, so the water has depth.
How often do plumes appear?
Every plume blooms in turn in three places, each bloom 14 to 31 seconds long (divided by speed), and they're spread through their loops, so a new one is always unfurling somewhere and the box never shows the same arrangement for long.
How do I change the ink?
Pass colors, such as ["var(--foreground)", "var(--primary)"], and plumes take turns with them; or set --ink-color-1 and --ink-color-2 in your CSS. By default it's indigo and ink blue on light, cyan and violet on dark.
How many plumes can I use?
count from 3 to 15 (9 by default). Each plume is a large texture on the graphics card, so keep it under 10 on a phone.
API Reference
Ink
<div> data-slot="ink"
colors?string[]
The ink's CSS colours, taken in turn from plume to plume. By default indigo and ink blue on a light page, luminous cyan and violet on a dark one.
count?number
How many plumes bloom at once, from 3 to 15, a third of them far back in the water. Each is a large texture on the GPU: keep it under 10 on a phone.
- Default
9
intensity?"subtle" | "medium" | "strong"
How dense the ink gets: subtle behind body text, strong for a
stage.
- Type
"subtle" | "medium" | "strong"- Default
"medium"
speed?number
How fast the plumes bloom and drift: 2 is twice as fast, 0.5 half as fast.
- Default
1
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
--ink-color-1string
The first ink (indigo on light, cyan on dark); --ink-color-2 and on for more.
--ink-speedstring
How fast the plumes bloom, a multiplier (1).
--ink-strengthstring
How dense the ink gets, a multiplier (1).
Related
- Pro


Watercolor Background
GradientsSoft watercolour washes on paper
- Pro


Drops Background
WavesWater ripples where drops land
- Pro


Smoke Background
WeatherSoft plumes drifting up
- Pro


Marble Background
TextureThe same swirls, frozen in stone
- Pro


Ripple Background
LightRings spreading from a point
- Pro


Metaballs Background
GradientsBlobs that fuse instead of fading