Introduction
picola is a fast, type-safe, extensible lightbox and image viewer — a dependency-free core with a first-class Svelte 5 adapter.
picola is a fast, type-safe, extensible lightbox and image viewer. It pairs a framework-agnostic, dependency-free core with a first-class Svelte 5 adapter, so you get modern, gesture-driven image viewing without fighting your framework or your CSS.
<script lang="ts"> import { Lightbox, type Slide } from 'picola/svelte'; import 'picola/picola.css';
const slides: Slide[] = [ { src: '/photos/1.jpg', width: 2400, height: 1600, alt: 'A river at dusk.' } ];
let open = $state(false);</script>
<button onclick={() => (open = true)}>Open gallery</button><Lightbox bind:open {slides} />That is a complete, keyboard- and gesture-driven viewer. Everything else in these docs is optional refinement.
Why picola
- Compositor-driven transitions — opening, closing, the clip reveal, backdrop fades and slide-stepping run on the compositor via the Web Animations API, so they keep their frame rate even while images decode on the main thread.
- Fly from the thumbnail — open and close animate from the source thumbnail.
When it is an
object-fit: covercrop, the transition reveals the full image with an animated clip instead of a plain scale. - Memory-disciplined — only the active slide ± 1 is mounted; images that leave the window are detached so the browser can reclaim their decoded pixels, and a source swap keeps the previous image up until the new one has decoded.
- Progressive loading — show a
placeholderinstantly, defer full resolution to azoomintentevent, then upgrade the source with zoom and pan preserved. Theslidesarray is reactive, so pagination syncs into the open viewer. - Native-feeling gestures — focal-point pinch / double-tap / wheel zoom,
rubber-band overscroll, velocity flicks, and drag- or pinch-to-dismiss with a
0–1progress value you can read from CSS. - Genuinely Svelte 5 — snippets and real components for the toolbar and caption
(wired through
{@attach}), and a genericSlide<T>that carries your own per-slide data through typed events. No SVG-string injection, no manualmount/unmount. - Styling that doesn’t fight back — flat single-class selectors and
zero-specificity (
:where) custom-property defaults, so you override by normal cascade order — no!important, and no@layerto lose against global resets. - Dependency-free core — the core has zero dependencies and owns gestures,
physics and transforms; the
picola/svelteadapter is ~15.6 KB min+gzip with icons, on a ~11 KB core (the stylesheet adds ~1.3 KB). Build an adapter for any framework.
How it’s built
The core owns gesture recognition, zoom/pan physics and transform rendering;
an adapter owns the DOM structure. The Svelte adapter under picola/svelte
is the reference implementation — it renders the chrome, wires up snippets, and
delegates all interaction to the core.
Because the core is framework-agnostic and dependency-free, you can drive it directly (see Framework-agnostic core) or build an adapter for any other framework.
Next steps
- Installation — add picola to your project.
- Quick start — a complete viewer in a handful of lines.
- Recipes — fly-from-thumbnail, custom toolbars, deferred loading, headless mode and more.
- API reference — every prop, event, snippet and type.
Early development. picola is pre-1.0 and its APIs may change before the stable release.