Skip to content

Image ​

Displays image resources, with an optional built-in preview feature.

Basic Usage ​

Basic image

Fit Mode ​

object-fit variants

cover (crop to fill)

contain (fit fully)

Set object-fit via fit, then fix the image container size with ::part(image) to achieve the crop effect.

Placeholder and Fallback ​

Loading placeholder

With placeholder, a light-gray placeholder is shown until the image finishes loading, then it switches to the image.

Load failure fallback

Default failure placeholder

Custom fallback image

When the image fails to load, an "Image failed to load" placeholder is shown by default; the fallback attribute can specify a fallback image URL, and if the fallback also fails, it falls back to the placeholder text.

Lazy Loading ​

Lazy-loading long list (loads image by image while scrolling)

With lazy, an image only starts loading when it enters the viewport; pair it with placeholder to show a "Loading" placeholder. Scroll down the list and watch the placeholder → loaded transition (images already in the viewport load immediately).

Preview ​

Click to preview (built-in overlay)

Click the image to open a full-screen preview overlay: the toolbar supports zoom in / out, rotate, flip horizontal / vertical, and download; after zooming in you can drag to pan and use the wheel to zoom. On touch screens, pinch with two fingers to zoom (anchored at the finger midpoint, which also pans as it moves) or drag with one finger to pan. Press Esc or click the mask to close. The close button is focused when opened, and focus is restored on close. Emits oas-preview (detail contains src).

When opened, the preview overlay is mounted to document.body (portal) so position: fixed keeps working even when the component sits inside a transform/filter ancestor. While portaled, ::part(preview-*) cannot pierce from the host — customize via CSS variables instead.

Gallery preview (multi-image paging)

Set preview-src-list (a JSON array of URLs) to enter gallery mode: use the side arrows, the toolbar paging buttons, or ←→ keys to page through, with an "n/total" counter. If an image fails to load, a failure placeholder (reusing the error slot content) is shown instead of a blank stage.

Infinite loop (infinite)

With infinite, paging wraps around: "next" on the last image returns to the first, and "prev" on the first image jumps to the last.

Thumbnail vs. Original ​

preview-src (separate thumbnail and original)

The list shows the src thumbnail, while the preview loads the high-resolution original from preview-src (the download link points to the original as well).

Controlled Preview ​

Controlled preview (preview-open + openPreview())

Open previewState: preview closed

The external button calls openPreview() to open; when preview-open is present it controls the open state — internal open/close (click / Esc / close button) reflects back to the attribute and emits oas-preview-change (detail { open }), and adding/removing the attribute drives the overlay as well (two-way sync).

Custom Toolbar ​

Custom toolbar (slot=toolbar + oas-toolbar-render)

With a template[slot="toolbar"], the template content is cloned into the preview overlay toolbar area, replacing the default button group (the original template stays in the light DOM; without a template the default toolbar remains). oas-toolbar-render is emitted on clone and on every open: use element (the toolbar container) and actions (the viewer commands) from the detail to wire custom buttons to viewer commands. The buttons above are wired — try them.

The detail of oas-toolbar-render is { element, actions }: element is the cloned toolbar container (bind button events on it; re-binding is idempotent); the actions command set is listed below (prev/next work in gallery mode and are no-ops in single-image mode):

CommandDescription
zoomIn / zoomOutZoom in / out one step (same transform state machine as the wheel and default buttons)
rotateLeft / rotateRightRotate 90° counter-clockwise / clockwise
flipX / flipYFlip horizontally / vertically
downloadTrigger a download of the current preview image
closeClose the preview overlay (equivalent to Esc / mask click)
prev / nextPrevious / next gallery image (respects the infinite boundary, same as default paging)

Host wiring example:

js
el.addEventListener('oas-toolbar-render', (e) => {
  const { element, actions } = e.detail
  element.querySelector('#my-zoom-in').onclick = actions.zoomIn
})

The shared preview of oas-image-group supports this as well: place a template[slot="toolbar"] directly inside the group and it is forwarded to the shared overlay. Custom toolbar buttons receive token-based base styles (readable in light/dark) and participate in the Tab focus trap.

Load Events ​

Load events (oas-load / oas-error)

Load success → oas-load

Load failure → oas-error

The main image emits oas-load on success and oas-error on final failure (both details contain src); during a fallback retry no oas-error is emitted — it fires only when the fallback also fails (detail.src is the fallback URL).

Custom Placeholder and Error Slots ​

Custom placeholder / error slots

slot="placeholder"

slot="error"

template[slot="placeholder"] / template[slot="error"] (or any element carrying the same slot attribute) is cloned into the corresponding placeholder area, taking precedence over the built-in text; a failed image inside a gallery preview reuses the error slot content as well.

Flip ​

Flip (flipX / flipY)

The toolbar provides "Flip horizontal" and "Flip vertical", composed into the same transform state machine as zoom, rotate, and pan — they compose without interfering with each other.

Drag to Pan and Wheel to Zoom ​

Drag to pan + wheel to zoom (large images)

After zooming in, press and drag on the preview image to pan (clamped to the visible bounds). Scroll the wheel inside the preview area to zoom (page scrolling is blocked). Zoom step and limits can be overridden with CSS variables (see the table below).

Photo Wall Composition ​

Photo wall (each image enters the same gallery)

A grid of thumbnails: clicking any one opens the shared gallery starting from that image (opening index matches the thumbnail src against the list).

Image Group (oas-image-group) ​

Image group (declarative photo wall → shared preview)

Put multiple oas-image elements inside oas-image-group and the container collects them into a shared gallery: clicking any image opens the preview from that image, and the side arrows / keyboard ←→ page through the whole set (n/total counter). A child's own preview click is taken over by the container as the shared gallery — no per-image preview-src-list needed.

Dynamically adding/removing children (or changing their src) syncs the gallery automatically; current optionally controls the current index — when present, clicks open at current and internal paging reflects back to the attribute; when absent, the attribute is not created and only oas-change is emitted (detail: { current, prev }, see the message feedback above); infinite is passed through to the shared preview.

Relation to preview-src-list: preview-src-list fits a data-array-driven single-entry gallery (one thumbnail representing the set); oas-image-group fits a declarative photo wall — every child image is naturally a gallery member, adding it to the DOM adds it to the set. Both share the same preview overlay capabilities (zoom/rotate/flip/download/Esc/mask/focus trap); children can still use preview-src for a dedicated preview URL, or preview-src-list to expand one child into multiple gallery entries. The group lays out as a wrapping flex row; the gap is customizable via the CSS variable --oas-image-group-gap.

Preview Zoom CSS Variables ​

CSS VariableDefaultDescription
--oas-image-zoom-step0.5Zoom in/out step (shared by toolbar buttons and the wheel)
--oas-image-zoom-min0.5Zoom lower bound
--oas-image-zoom-max3Zoom upper bound

Override them on the host element or at the theme level, e.g. style="--oas-image-zoom-max: 5".

Explicit Dimensions and Referrer Policy ​

width / height set explicit dimensions: numbers are treated as px, and any CSS size string (e.g. 50%) passes through as-is onto the inner img (the max-width: 100% responsive constraint is preserved); empty values clear the sizing back to auto layout. referrerpolicy passes through to the inner img to control the privacy policy (e.g. no-referrer); an empty value falls back to the browser default.

Explicit width / height

referrerpolicy pass-through

API ​

oas-image ​

Attributes ​

AttributeDescriptionTypeDefault
altAlternative text——
fallbackFallback image URL to switch to on load failure; when not set, shows the "Image failed to load" placeholderstring—
fitobject-fit valuestring—
heightExplicit height (same rules as width)string—
infiniteLoop around the first/last gallery imageboolean—
lazyLazy load: the image starts loading only when it enters the viewport (IntersectionObserver); loads immediately when already in the viewport; falls back to eager loading when unsupportedboolean—
placeholderShow a light gray placeholder before the image finishes loadingboolean—
previewEnable built-in preview: click to zoom + zoom/rotate/download + Esc to close + focus trapboolean—
preview-openControlled preview open state (controlled when present, two-way with oas-preview-change; see also openPreview())boolean—
preview-srcOriginal image URL for preview (thumbnail/original separation; falls back to src)string—
preview-src-listGallery preview: JSON array of URLs; prev/next paging + counter + keyboard ←→ after openingstring—
referrerpolicyReferrer policy passed through to the inner imgstring—
srcImage URLstring—
widthExplicit width (numbers become px; any CSS size string passes through; empty restores auto)string—

Events ​

EventDescription
oas-errorImage failed finally (fallback chain exhausted), detail: { src }
oas-loadImage loaded successfully, detail: { src }
oas-previewPreview overlay opened, detail: { src }; closing the overlay does not emit an event
oas-preview-changePreview open state changed, detail: { open }
oas-preview-navGallery page change/jump, detail: { index, src }; lets the oas-image-group container take over the index
oas-toolbar-renderCustom toolbar render notification (fired on clone and on every preview open; host re-binding is idempotent), detail { element, actions }: element is the cloned toolbar container, actions is the viewer command set

Slots ​

NameDescription
template[slot="error"]Custom error placeholder content (shared by the main image and gallery preview failures)
template[slot="placeholder"]Custom loading placeholder content (gray block + text by default)
template[slot="toolbar"]Custom preview toolbar content: cloned into the overlay toolbar area, replacing the default button group (defaults remain when absent). Emits oas-toolbar-render on clone and on every open (detail { element, actions }); action commands: zoomIn/zoomOut/rotateLeft/rotateRight/flipX/flipY/download/close/prev/next (prev/next are no-ops in single-image mode)

oas-image-group ​

Attributes ​

AttributeDescriptionTypeDefault
currentCurrent gallery index (optional controlled): when present, clicks open at current, internal paging reflects back to the attribute, and external changes drive the preview jump; when absent the attribute is not created and only oas-change is emitted——
infiniteLoop paging around the first/last image (passed through to the shared preview host)boolean—

Events ​

EventDescription
oas-changeGallery page changed, detail: { current, prev }
oas-previewShared preview overlay opened, detail: { src } (src is the current image URL)

Slots ​

NameDescription
defaultGallery members (oas-image)
template[slot="toolbar"]Forwarded to the shared preview host: customizes the shared preview overlay toolbar (clone replaces the default button group + oas-toolbar-render command channel, same as oas-image)

CSS Variables ​

CSS VariableDefault
--oas-image-group-gapvar(--oas-space-3)

Released under the MIT OR Apache-2.0 License.