Esc

comark-zoom

Zoom

Click an image or any block to zoom it out of its place. Escape, Back, or a click around it closes it.

Playground

Office correlations dashboard

Click an item to zoom it; Escape, Back, or a click around it closes it. Enter or Space opens a focused item, and focus returns to it when the view closes.

Content images zoom on their own, except images inside links, which keep their link. The zoomed view shows the image's alt text as its title, and an image grows no larger than its natural size, so it stays sharp.

Give an image a data-zoom-src to load a larger file when it opens. The zoom shows the page's image until the larger file has loaded, and the strip of a group keeps the page's images. To keep one image from zooming, give it zoom=false:

![Company logo](/logo.png){zoom=false}
md

Zooms any block: a table, a code block, a diagram, or several of them together.

Playground
Attempt Wait
1 1 s
2 4 s
3 16 s
Prop
title Heading of the zoomed view.
group Items with the same group page through one zoomed view.
#id, .class Go on the block, as on any other.

Items in one group page through a single zoomed view with a strip of them at the bottom. Arrow keys and the strip move between them. Items that are hidden when the view opens, such as those in a closed tab, are left out.

Playground
Filter toolbar wrapping
Filter toolbar on one row

data-zoom-aside names an element, by selector, that the zoomed view shows beside the item at its own size. A caption stays readable however far the item zooms. On a narrow screen it sits below. comark-annotate uses it for a screenshot's notes.

The zoom takes the first match that neither holds the item nor sits in it. It looks in the item's innermost data-zoom-context, or else in its parent.

<figure>
  <img data-zoom data-zoom-aside="figcaption" src="pigeons.png" alt="Pigeons on the roof by week">
  <figcaption>Pigeons dip in week 3, when the falcon visited.</figcaption>
</figure>
html

The options go under zoom in comarkUi(), or to zoom() when you use it alone. zoom: false in comarkUi() turns zoom off.

Option Default
images true false leaves images alone, so only ::zoom blocks and images you mark with {data-zoom} zoom.

The zoomed view fires comark-zoom:open, comark-zoom:change, and comark-zoom:close on the item. open and change carry the dialog's header and footer, and a layer over the zoomed content, sized to it, where a host can draw its own pins or controls.

copyOf(element) finds the copy of a page element in the zoomed view, and originalOf(element) goes back, so a pin can follow what it points at. Both return null for anything the zoom doesn't show.

document.addEventListener("comark-zoom:open", (event) => {
  const pin = document.createElement("button");
  pin.textContent = "1";
  pin.style.cssText = "position:absolute;left:40%;top:20%";
  event.detail.layer.append(pin);
});
ts

comark-ui brings comark-zoom and registers it. To use it alone, install it and pass the renderer's components:

pnpm add comark @comark/html comark-zoom
import { createHtmlRenderer } from "@comark/html";
import zoom, { components } from "comark-zoom/html";

const render = createHtmlRenderer({ plugins: [zoom()], components });
ts

For Vue, React, or Svelte, import from comark-zoom/vue, comark-zoom/react, or comark-zoom/svelte. Renderers covers server rendering, pages without a renderer, and zoom with other plugins.

The zoomed view follows the shared tokens in Theming, and two variables of its own change the backdrop. The rules sit in a comark CSS layer, so a plain rule of your own wins over any of them.

Token Used for
--comark-background The backdrop
--comark-foreground The header's text, the current thumbnail's border
--comark-muted The counter
--comark-border The thumbnails' borders
--comark-accent Hovered close and arrow buttons
--comark-ring Focus rings on items and buttons
--comark-radius Button and thumbnail corners
--comark-font The header

The tokens resolve on .cz-dialog, so tokens set there theme the zoomed view alone.

The zoomed view sits at the end of body, so set these on :root, body, or .cz-dialog:

Variable Default Used for
--cz-backdrop --comark-background at --cz-backdrop-opacity The backdrop's color
--cz-backdrop-opacity 96% How much of --comark-background the backdrop mixes in
Selector Is
[data-zoom] An item on the page that zooms
.cz-dialog The zoomed view, with data-aside when it shows a caption beside the item
.cz-backdrop The layer behind everything else
.cz-header, .cz-title, .cz-count, .cz-close The top row: title, position in a group, and the close button
.cz-stage, .cz-item The area the item zooms into, and the zoomed copy
.cz-prev, .cz-next The arrows of a group, both .cz-nav
.cz-aside The caption beside the item, from data-zoom-aside
.cz-strip, .cz-thumb The row of thumbnails, and each one, with aria-current="true" on the open one

The zoomed copy leaves the page, so it loses rules that match through its ancestors, such as .post img. An item that needs them names those ancestors with data-zoom-context, a selector. The copy then goes inside empty copies of every ancestor that matches:

<article class="post">
  <img data-zoom data-zoom-context=".post" src="pigeons.png" alt="Pigeons on the roof by week">
</article>
html

A dark backdrop that lets the page show through:

:root {
  --cz-backdrop: rgb(0 0 0 / 0.8);
}

.cz-dialog {
  --comark-foreground: #fafafa;
  --comark-muted: #a1a1a1;
}
css

To try it, paste it into Extra CSS in the playground's Theme pane.