Everything on this page is host-page furniture: a sticky masthead, a
centred reading column, serif body copy and a footer. The viewers below
are dropped into that flow exactly as a third-party site would embed
them, with no styling help from the demo stylesheet.
Scroll slowly. Watch what happens to the controls when the element is
narrower than the window, when it is shorter than its content wants to
be, and when the page itself is doing the scrolling.
The manuscript, in the reading column
The first embed sits in the article column, so its width comes from the
host page rather than the viewport. Container queries mean it should
adopt its compact layout here even on a wide monitor.
Wunder der Vererbung, Lux-Lesebogen 103. Embedded at the article
column width.
Text continues after the viewer. The element must not bleed outside its
figure, must not introduce horizontal page scrolling, and must not
steal the page's scroll when a finger crosses it.
A second paragraph, so there is something to scroll past on a phone
before the next section arrives.
The story viewer, full-bleed on a dark section
Here the host section is wider than the reading column and sets its
own dark background and light text. Inherited colour and font choices
should not leak into the viewer's own chrome.
Content below the story viewer, to confirm the page keeps scrolling
normally once the pointer leaves the element.
A viewer in a narrow aside
The column beside this text is 22rem wide on desktop and collapses
to full width on smaller screens. The viewer inside it is a good
test of element-relative breakpoints: the window may be 1600px wide
while the element is barely 350px.
If the layout responded to the viewport instead of the element, the
aside would show a desktop layout crammed into a phone-sized box.
It should instead look like the phone layout, with the compact
control rail and a persistent toolbar.
A deliberately short embed
Some hosts pin a height. This one sets
mango-viewer { height: 400px }, which used to squeeze the
image to nothing and clip the transport controls.
Opening on a chosen page and detail
An embedder often wants to point at one page, not the front cover —
the plate a paragraph is discussing, framed the way the author meant
it. That is a property of the embed, so it belongs in the
config attribute rather than in a script:
initialCanvasIndex picks the page and
initialViewBox frames a region of it, in image
coordinates.
The viewer below opens on page 7 of 36, already zoomed to a
1900 × 1300 region of a 2411 × 3372 scan.
No host-page JavaScript runs at all — reload and it lands there
every time.
Deep-linked at embed time: page 7, framed on the upper illustration.
The same recipe, other collections
Nothing above is specific to that one manifest. These two embeds come
from different institutions and open on different parts of their
canvas: the left one high up on the sitter's face, the right one well
past the midpoint of a tall canvas. Both are a single
config attribute, and the coordinates are in each
image's own pixel space — a 2087 × 2550 photograph and a
4066 × 6684 one — so the same region numbers would mean
quite different things in each.
Harvard Art Museums — Van Gogh, Self-Portrait Dedicated to
Paul Gauguin. Opened on 560, 880 · 980 × 800.
Yale Center for British Art — Hayman, The Good Samaritan.
Opened at 700, 3900 · 2200 × 1800, well down a
6684-pixel-tall canvas.
Because the framing is expressed in image coordinates rather than
screen ones, each embed keeps pointing at the same part of the
painting whatever width the host column happens to be. Narrow the
window and the region stays put; only the surrounding margin changes.
The same two settings, back in the column
Width is the variable worth watching. These two are the same recipe
again — different manifests, different regions — but back at reading
column width, so each element is about half as wide as the pair above.
The viewer swaps to its compact layout at this size: the control rail
wraps to a second row and the thumbnail strip sheds entirely.
The framing is unaffected by any of that. A region is a property of
the image, not of the surface it is drawn on, so both embeds open on
exactly the part they were told to — the manuscript on a painted
figure well down the page, the photograph on its right-hand side.
Bodleian Library, MS. Ind. Inst. Misc. 22 — a
5392 × 8158 page, opened at
900, 3000 · 2600 × 2200.
IIIF Cookbook, recipe 0005 — a 4032 × 3024 landscape
image, opened on its right-hand side at
2400, 900 · 1500 × 1300.
Driving the viewer from the host page
The same three things are settable at any time through the element's
public API. The buttons below are ordinary host-page buttons — they
are not viewer chrome, and they reach the viewer only through the
methods on the element.
Pages move with setCanvasByIndex(i), zoom with
setZoom(percent) where 100% is fit-to-view, and position
with panTo(x, y) or the fuller
setViewBox({ x, y, w, h }). The readout underneath is fed
by the pageChange and zoomChange events, so
it also tracks whatever you do with the viewer's own controls.
Panning is clamped to the edges of the image, which is why the
position buttons do most of their visible work vertically on a
portrait scan: at fit-to-view the whole page width is already on
screen, so there is nowhere sideways to go until you zoom in.
Page
Zoom
Position
Page – · zoom
– · viewBox
–
Every button above is host-page JavaScript calling the element's
public methods.
Checklist while resizing this page: nothing clipped, no horizontal page
scrollbar, the play button and scrubber always visible, the icon rail
swipeable where it overflows, and fullscreen covering the sticky
masthead rather than sitting under it.
A final run of body copy so that both viewers have content above and
below them at every screen size, which is how they will actually be
met by readers.