back

Tutorial 03 · Frame an existing page

One function call wraps this entire page in a zoom/pan surface and gives you a Panel API viewport to attach panels to. xy ratio preserved.

The minimal recipe

<script type="module">
  import panel from 'https://cdn.jsdelivr.net/npm/panel-api/+esm';
  import { framePage } from 'https://cdn.jsdelivr.net/npm/panel-api/zui/+esm';

  const viewport = framePage();   // wraps document.body content
  panel.attachViewport(viewport); // panels now know about ZUI

  panel.open("", "Hello", { width: 320 }).setHTML("Hello!");
</script>

What framePage() does

  1. Moves your current body content into a new .panel-api-surface element.
  2. Puts that surface inside a fixed-size, clipped .panel-api-viewport.
  3. Injects minimal styles to make the layout work.
  4. Wires default pan/zoom interactions (override with { interactions: false }).
  5. Returns a PanelViewport you can pass to panel.attachViewport().

No restructuring

Drop in two imports and a call. Existing layout, scripts, and event handlers still work.

Preserves xy ratio

A single uniform scale applies to both axes — content never looks squashed.

Panels stay crisp

Panels float in a sibling layer that doesn't transform with the world.

Try it