GitHub

Geometric image placeholders for Svelte 5

No blur. The placeholder is the image, approximated by geometric shapes fitted at build time — and because they're stored in fit order, replaying them makes the picture visibly sharpen until the real photo crossfades in.

In production on szkolyjogi.pl — 700+ listing photos resolve from their geometric preview — and kurcz.pl.

Playground

fitted live in your browser — in production this runs at build time
1200×800
Inline placeholder
8.0 KB
8.0 raw
Lighter first paint
vs. the photo
Shapes
100
in fit order
Fit time
build
prebuilt
Image
Pick any photo — it's geometrized on your device, nothing is uploaded.
Shape types
Reveal
how each shape animates in — replays on change
Object fit
cover crops; contain letterboxes — SVG matches the photo
more shapes = more detail, bigger payload
lower = more layered, translucent shapes
optional early-exit when the approximation is “good enough”

How it works

a real preview in a couple of KB — no blank box, no layout shift, no blur
  1. 01

    Fit at build time

    A Vite plugin fits geometric shapes to each ?geometrize import — cached on disk by content hash, so clean rebuilds skip work you've already done. Or batch CMS photos with npx svelte-geometrize. The expensive part never ships.

  2. 02

    Paint instantly, no layout shift

    The placeholder is inline in the server-rendered HTML, so a real preview fills the box before the photo's first byte arrives — and because its aspect ratio is reserved, nothing below it ever jumps.

  3. 03

    Reveal, then crossfade

    revealMs paces the shapes across a fixed budget; pure CSS plays before hydration and respects reduced motion. Then the photo dissolves over the same structure — content-aware, not a blur.

Use it

register the Vite plugin, then import with ?geometrize
import { GeometrizedImage } from '@nomideusz/svelte-geometrize';
import placeholder from './photo.jpg?geometrize';
import src from './photo.jpg';

<GeometrizedImage {placeholder} {src} alt="Sunset over mountains" revealMs={850} />

// build / ingest also need: pnpm add -D sharp
// npx svelte-geometrize ./photos --out ./placeholders

Full options and the Node API are in the docs.