For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. The asciicn agent skill, for building any ASCII effect on the engine, is at /.well-known/agent-skills/asciicn/SKILL.md.

ASCII reveal

An image that resolves out of glyphs: cells lock in and hand over to the real photo along a sweep, on view, on hover or on cue.

Controls
Photo
Trigger
Direction
Charset
Colour
Duration2400ms
Cell9px

Installation

pnpm dlx shadcn@latest add https://asciicn.dev/r/ascii-reveal.json

Usage

import { AsciiReveal } from "@/components/asciicn/ascii-reveal";
 
export function Hero() {
  return (
    <AsciiReveal
      src="/photos/launch.jpg"
      alt="The rocket on the pad at dawn"
      direction="down"
      className="w-full max-w-xl"
    />
  );
}

AsciiReveal starts as the picture drawn in glyphs. It samples the photo with the same area-averaging sampler as AsciiImage, so every glyph is the average of the pixels under its cell.

When the reveal runs, an edge sweeps across the picture. Cells at the edge flicker through glyphs in the accent colour, then lock in as the photo. Behind the edge the real photo shows. Ahead of it the glyphs hold. The edge bends a little and has some grain, so cells hand over one by one instead of in straight lines.

trigger sets what starts it:

  • view reveals once, when the image scrolls into view.
  • hover reveals on hover or keyboard focus, and goes back to glyphs on leave. On a touch screen a tap toggles it.
  • manual follows the revealed prop, so you can tie it to your own state.

The box keeps the image's aspect ratio. Pass ratio to reserve the space before the image loads, or set your own aspect-* class.

Examples

Hover cards

Each card reveals on hover or focus and sweeps back on leave. A short duration keeps them quick under the pointer.

Full-width radial reveal

direction="radial" opens the photo from the centre out. This one is Braille in truecolor and reveals once, when it scrolls into view. Press Replay to see it again.

Props

PropTypeDefault
src

Image URL. Files on another origin need CORS headers, or the canvas can't read their pixels.

Type: stringDefault –
alt

What the image shows, passed to the <img>. Pass "" for a decorative image.

Type: stringDefault –
trigger

view reveals once on scroll into view. hover reveals on hover or focus. manual follows revealed.

Type: "view" | "hover" | "manual"Default "view"
revealed

With manual: true shows the photo, false the glyphs.

Type: booleanDefault false
direction

Which way the edge travels. radial opens from the centre. random dissolves in patches.

Type: "down" | "up" | "left" | "right" | "radial" | "random"Default "down"
duration

Length of one full sweep in milliseconds. A reveal that turns back halfway takes half as long.

Type: numberDefault 2400
accent

Colour of the glyphs at the edge. A palette name, a CSS variable or any CSS colour.

Type: AsciiColorDefault "orange"
ratio

Width over height of the box.

Type: numberDefault the image's own, 4/3 before it loads
charset

Which glyphs draw the picture.

Type: "standard" | "dense" | "blocks" | "quadrants" | "braille" | "cp437" | "petscii" | "katakana" | "dots" | "edge"Default "standard"
chars

A custom ramp from empty to dense, such as " .oO@". Wins over charset.

Type: stringDefault –
colorMode

mono draws in one ink. truecolor takes each cell's colour from the photo. duotone reads tones through ramp.

Type: "mono" | "truecolor" | "ansi16" | "duotone" | "palette"Default "mono"
phosphor

With mono: a CRT ink and its dark glass.

Type: "p1" | "p3" | "ibm" | "blueprint"Default –
ramp

With duotone: a named ramp or your own stops, dark to light.

Type: RampName | string[]Default "mainframe"
ansi

With ansi16: which 16-colour table.

Type: "vga" | "xterm"Default "vga"
grade

Tone and colour grading before glyphs are chosen.

Type: { brightness?, contrast?, gamma?, saturation? }Default –
invert

true: dark pixels draw dense glyphs. false: bright pixels do. Unset, it follows the page.

Type: booleanDefault follows the theme
threshold

Braille and quadrants: the tone that lights a dot.

Type: numberDefault 0.5
edgeThreshold

With the edge charset: how strong a contour must be to draw a stroke.

Type: numberDefault 0.22
dither

Ordered dithering between glyph levels and dots.

Type: "none" | "bayer2" | "bayer4" | "bayer8" | "blue-noise"Default "blue-noise" for Braille and quadrants, else "none"
background

transparent draws glyphs only, over whatever is behind.

Type: "paper" | "transparent"Default "paper"
fx

CRT effects over the glyphs: scanlines, bloom, vignette.

Type: PostFxDefault –
cell

Glyph cell height in CSS pixels.

Type: numberDefault 9
animate

false swaps between glyphs and photo without a sweep, as reduced motion does.

Type: booleanDefault true
crossOrigin

Passed to the image requests.

Type: "anonymous" | "use-credentials"Default "anonymous"
handle

Filled with a handle for export: the glyph layer as text, ANSI, SVG or PNG.

Type: RefObject<AsciiHandle | null>Default –

Notes

  • The real <img> is always in the page and carries alt, so screen readers read the image in either state. The glyph layers are aria-hidden.
  • The image loads lazily. The glyphs sample it once the box comes within about 300 px of the viewport, and the <img> uses loading="lazy".
  • With reduced motion, or animate={false}, there is no sweep. A view reveal shows the photo straight away. A hover reveal shows the glyphs until you hover or focus it, then swaps to the photo. A manual reveal shows whatever revealed says.
  • The sweep is the only motion. Before it starts and after it ends the component draws nothing new until a prop or the box size changes. Offscreen and in a hidden tab the sweep pauses where it is.
  • During the sweep the photo is drawn through a mask of one pixel per cell, so the handover lines up with the glyph grid. At rest the <img> itself shows.
  • With trigger="hover" the box is focusable. If it sits inside a link or a button, use trigger="manual" and drive revealed from that element's hover and focus instead.
  • The sample photos are public domain, from NASA, the Hubble Heritage Team and Ansel Adams for the US National Park Service, all from Wikimedia Commons.