If you have seen the hero on landonorris.com, you know the effect: you drag the cursor across his face and a helmet appears where you pass, torn open along a wet ragged edge, then it heals back when you leave.
revealed is that effect as a library. Two images stacked in one box, the top one tears open where the visitor drags, the one underneath shows through, and it closes again behind the cursor.
npm i revealed
import { Revealed } from "revealed/react";
<Revealed front="/before.webp" back="/after.webp" />
That is the whole setup. It renders one div, injects a canvas and the two image plates, takes the aspect ratio from the front image, and starts. No config, no refs, no effect hooks.
19.2 kB gzipped. Zero runtime dependencies. React is an optional peer, used only by the /react entry. There is a vanilla RevealField class and a CDN build too.
Why it does not look like a normal hover mask
I built this after failing to copy that hero. I assumed it was a brush trail: paint into a mask, decay the mask, threshold it, mix two images. Two things about theirs I could not reproduce that way. The reveal keeps spreading for about a second after you stop moving, and it has holes in it, islands of the original image standing inside an area that is otherwise uncovered.
Their bundles are on a public CDN, so I read the shader. It is not a brush trail. It is a fluid solver, and the cut thresholds the velocity field rather than a painted mask. It reveals where the fluid is moving, not where the pointer has been. That one decision is where both behaviours come from: the wave outliving the stroke is momentum, and the holes are what thresholding an incompressible field gives you, because a vortex core has no velocity at its centre while everything around it does.
revealed reproduces that character without shipping a fluid solver. The mask is RGBA8 and only the red channel holds the reveal, so the velocity lives in the two spare channels. No extra render target, no extra shader program, one extra texture fetch. WebGL1 throughout, no extensions, no float textures.
Measured on Intel integrated graphics: the leading edge travels 44px over 2.4s after the pointer stops, against a control that recedes 34px. At 1500x1192 the wave costs 11.4ms per frame versus 10.5ms without it, which is inside run-to-run noise.
Three layers, the third optional
A front plate, a back plate, and an optional skeleton layer: line art of the hidden image, ghosted onto the front so people know there is something to find, and wiped exactly where the back plate is already uncovered. It can also be a real 3D wireframe, behind the revealed/mesh subpath so the core stays small.
One number, three names
<Revealed front="..." back="..." brush={{ persist: true }} /> // stays uncovered
<Revealed front="..." back="..." brush={{ spotlight: true }} /> // torch, no trail
<Revealed front="..." back="..." progress={scrollProgress} /> // no pointer at all
persist is a heal rate of zero. spotlight is a heal rate of infinity. trail is everything in between. progress drives the same cut from scroll position, so the reveal wears the identical wet edge with no pointer involved.
Six presets
<Revealed front="..." back="..." edge="ink" />
liquid is the default. plain gives you a quiet, classic dissolve with no wave and no bubbles if the fluid character is not what you want.
It fails safely
The front plate is a real <img> in the DOM the whole time, so it is what you see when anything goes wrong: no WebGL, a software renderer, prefers-reduced-motion, a failed shader link, a 404 on a plate, or a lost context. A restored context brings the effect back on its own. Nothing ever renders a hole where your image should be.
It also pauses itself off screen and on hidden tabs, and it is SSR-safe: importing it on the server touches nothing, and revealed/react ships its own "use client", so no dynamic() wrapper.
Links
- Docs and a playground with every option wired to a control: revealed.idlee.xyz
- Source, MIT: github.com/idleCyrex/revealed
- npm
Other things I have made
topolines is the same idea applied to backgrounds: animated topographic contour fields for React, one component, zero dependencies, drawn on the GPU. It is what draws the contour lines behind the revealed docs site.
npm i topolines
If you build something with either of them I would like to see it.




Top comments (1)
A star on github would be really appreciated<3
github.com/idleCyrex/revealed