Panzoom

A lightweight, dependency-free library for adding smooth pan-and-zoom interactions to any HTML or SVG element using CSS transforms.

Library
npm
v4.6.2
2,461stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
64/100Good
Development Activity56
Maintenance28
Community72
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture80
Code Quality85
Innovation80
Learning Curve55

Panzoom is a small (~3.7kb gzipped) JavaScript/TypeScript library that adds panning and zooming behavior to a single DOM element. Instead of manipulating top/left/width/height, it applies CSS transforms (translate + scale), which lets the browser use GPU acceleration and means the target element can be literally anything: an image, an iframe, a video, an SVG diagram, or a block of text.

The library binds to native Pointer Events (falling back gracefully where unsupported) to unify mouse, touch, and stylus input, and includes first-class support for pinch-to-zoom gestures, mouse-wheel zooming anchored to the cursor, and containment rules that keep the element from panning fully outside (or fully covering) its parent. It ships as UMD, ESM, and CommonJS builds with full TypeScript types, and exposes an imperative API alongside a set of CustomEvents (panzoomstart, panzoomchange, panzoompan, panzoomzoom, panzoomreset, panzoomend) so it can be wired into any framework without a dedicated binding layer.

What You Get

  • A ~3.7kb gzipped, zero-dependency library distributed as UMD, ESM, and CommonJS builds
  • Complete TypeScript type definitions for every option, method, and event payload
  • An imperative API — pan, zoom, zoomIn, zoomOut, zoomToPoint, zoomWithWheel, reset, setOptions, destroy, getPan, getScale — covering the full interaction lifecycle
  • Built-in multi-touch support (pinch-to-zoom, optional simultaneous pinch-and-pan) with no separate touch plugin required
  • A CustomEvent-based notification system (panzoomstart/change/pan/zoom/reset/end) for hooking into pan/zoom state from any framework

Common Use Cases

  • Adding pan/zoom to embedded high-resolution images, architecture diagrams, or maps
  • Building interactive SVG canvases such as org charts, flowcharts, or floor plans
  • Layering zoom/pan controls over canvas-rendered PDF or document viewers
  • Product photo or technical-drawing zoom viewers in e-commerce and configurator UIs
  • Dropping pan/zoom into React, Vue, or plain JS apps without a framework-specific dependency

Under The Hood

Architecture The core lives in a single factory function, Panzoom(elem, options) in src/panzoom.ts, that closes over local mutable state (x, y, scale, isPanning) rather than using a class hierarchy, delegating narrow DOM concerns to small single-purpose modules (css.ts for style/dimension reads, events.ts for pointer-event binding, pointers.ts for multi-touch tracking, plus isAttached.ts, isExcluded.ts, and isSVGElement.ts). Every state change funnels through two choke points — constrainXY/constrainScale, which apply axis-lock, containment, and min/max-scale rules — before reaching setTransformWithEvent, which batches the actual style write inside requestAnimationFrame and fires the corresponding CustomEvent, keeping rendering and event dispatch synchronized. Because every public method (pan, zoom, zoomToPoint, reset) routes through those constrain functions, changing their contract would ripple through the entire public API at once.

Tech Stack Written in TypeScript (~6.0.2) with strict compiler settings, bundled via Rollup with rollup-plugin-typescript2 into UMD/ESM builds, then minified with uglify-js and measured by a custom gzip-size task; a small polyfills.js patches CustomEvent support for older browsers. The published package carries zero runtime dependencies. Linting runs through ESLint 9’s flat config with typescript-eslint, formatting through Prettier, commit messages are enforced via commitlint + husky, and releases are automated end-to-end with release-it (conventional-changelog plus GitHub releases). A separate Webpack 5 + React 19 demo site exists for documentation/examples but ships independently of the library.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search