Contact Us

Image Lightbox

DOC-00088 reference implementor, developer

Overview

The Image Lightbox provides a full-screen overlay for viewing images at a larger size than their inline presentation. CORE-OWNED. Requirements: REQ-00049 (lightbox), REQ-00050 (focus trapping), REQ-00053 (focus restoration), REQ-00054 (scroll locking).

The lightbox backdrop uses --st-color-overlay-scrim at 80% alpha so the overlay remains semantically tied to the theme token surface instead of a raw color literal.

Who this is for

  • Implementors adding lightbox behavior to images in pages and articles
  • Developers customizing lightbox configuration, gallery grouping, or the rehype plugin

Two components work together:

  • Lightbox.astro (src/core/components/ui/Lightbox.astro) — the full-screen overlay modal. Uses native <dialog> for dialog semantics, focus trapping, scroll locking, and Escape-to-close.
  • LightboxImage.astro (src/core/components/ui/LightboxImage.astro) — the Astro template trigger component. Renders a <a data-lightbox><img /></a> wrapper with typed props.

A rehype plugin (rehype-lightbox-images.ts) provides the markdown/MDX integration path, wrapping rendered <img> elements in the same <a data-lightbox> markup at build time.

Usage Paths

Astro templates

Use LightboxImage for typed prop access to all features (hi-res source, explicit captions, named gallery groups):

---
import LightboxImage from "@core/components/ui/LightboxImage.astro";
import Lightbox from "@core/components/ui/Lightbox.astro";
---

<LightboxImage src="/images/photo.jpg" alt="A scenic mountain view" />
<LightboxImage
  src="/images/team.jpg"
  alt="Team photo"
  hires="/images/team-hires.jpg"
  caption="The full team at our annual retreat"
  group="team"
/>

<Lightbox />

When using LightboxImage in Astro templates, the author must include <Lightbox /> on the page. For collection-routed pages (articles, pages), the template route includes <Lightbox /> automatically when lightbox is enabled.

Markdown/MDX content

For markdown/MDX content in the articles and pages collections, lightbox is controlled via configuration:

  • Site config (src/site/config/platform.config.ts): per-collection defaults via platformConfig.lightbox.collections
  • Frontmatter: per-page override via lightbox: true or lightbox: false

When enabled, the rehype-lightbox-images plugin wraps eligible <img> elements in <a data-lightbox> at build time. All wrapped images join a single implicit gallery.

LightboxImage Props

PropTypeRequiredDefaultDescription
srcstringYesImage source URL
altstringYesAlt text for the image
hiresstringNoHi-res image source for the overlay
captionstringNoExplicit caption (overrides alt text in overlay)
groupstringNo"implicit"Gallery group name for independent gallery navigation
classstringNoAdditional CSS classes for the wrapper <a> element

Configuration

Site-level (site.schema.tsplatform.config.tssite.ts)

// src/site/config/platform.config.ts
export const platformConfig = {
  // ...
  lightbox: {
    ...DEFAULT_SITE_CONFIG.lightbox,
    collections: { articles: true }, // default
  },
};

The collections record maps collection names to boolean defaults. Collections not listed default to false. The type is constrained to "articles" | "pages". site.ts assigns this same value to siteConfig.lightbox so route templates and the markdown rehype plugin use the same source.

Per-page (frontmatter)

lightbox: true   # Enable lightbox for this page (overrides collection default)
lightbox: false  # Disable lightbox for this page
# Omit to defer to collection default

Resolution order: frontmatter → site config collection default → false.

  • Implicit gallery: All ungrouped lightbox images on a page (no group prop, or group="implicit") form one gallery.
  • Named groups: Use the group prop to create independent galleries (e.g., group="before-after"). Each named group navigates independently.
  • Single images: An image that is the sole member of its group opens without navigation controls.

Accessibility

  • role="dialog" and aria-modal="true" via native <dialog> with .showModal()
  • Visually-hidden “Image viewer” label via aria-label
  • Focus trapping within the overlay while open (REQ-00050)
  • Focus restoration to the trigger element on close (REQ-00053)
  • Initial focus moves to the close button on open
  • Scroll locking while overlay is active (REQ-00054)
  • Keyboard: Escape closes, Left/Right arrows navigate gallery, Tab cycles interactive elements
  • Touch: swipe left/right navigates gallery on touch devices
  • Transitions respect prefers-reduced-motion
  • Semantic z-index via var(--st-layer-modal-backdrop) / var(--st-layer-modal-surface) in scoped <style> (REQ-00189)

Progressive Enhancement

Without JavaScript, lightbox-enabled images render as <a href="[src]"><img /></a>. Clicking opens the full-size image directly in the browser tab. The inline image display is unaffected. When a hires prop is provided, the <a> href points to the hi-res source.

CSS API

ClassElementDescription
.lightboxRoot wrapperComponent root element
.lightbox__backdropOverlay backdropSemi-transparent background
.lightbox__panelDialog panelFull-screen flex container
.lightbox__closeClose buttonTop-right close control
.lightbox__contentImage + captionCentered content container
.lightbox__image<img> elementFit-to-viewport image
.lightbox__captionCaption textBelow-image caption
.lightbox__navNav button (both)Prev/next navigation controls
.lightbox__nav--prevPrev buttonLeft-positioned nav control
.lightbox__nav--nextNext buttonRight-positioned nav control
.lightbox-imageLightboxImage <a>Trigger wrapper class
REQ-00049 implemented An Image Lightbox component shall be provided.
REQ-00050 normative Modal/lightbox components shall implement focus trapping and restoration.
REQ-00053 normative Transient interactive UI shall restore focus upon dismissal.
REQ-00054 normative Modal and overlay components shall define scroll locking behavior while active.
REQ-00225 implemented The lightbox shall integrate with markdown content via a build-time rehype plugin that wraps eligible images in lightbox-enabled links, enabling lightbox behavior without manual markup in content files.
REQ-00226 implemented Lightbox enablement shall resolve through a three-level configuration hierarchy: content frontmatter override, collection default, system default (false), allowing per-page, per-collection, and system-wide control.
REQ-00227 implemented The lightbox shall support gallery grouping via data attributes, keyboard navigation (arrow keys for gallery traversal, Escape to close), and touch swipe gestures for mobile navigation.
REQ-00267 implemented Configuration values consumed by build-time plugins (rehype, remark) in astro.config.mjs shall be defined independently of site.ts, because Vite path aliases are not available during Astro config parsing. Site overrides affecting plugin behavior shall be synchronized in both astro.config.mjs and site.ts.

Search

Search across pages and articles. Use arrow keys to navigate results.

Search across pages and articles.

Loading search...

Search is unavailable. Please try again later.

    No results for ""

    Try different keywords or fewer words.