Image Lightbox
The lightbox opens an image at full viewport size in a native <dialog>. It is one implementation shared by the Fitted Image block (a single image) and the Swiper Gallery block (every slide): the same trigger markup from method_get_lightbox_attributes() (lib/blocks.php), the same script in lib/blocks/utils/lightbox.js, the same styles in global.scss.
How it works
- The trigger is a real link.
method_get_lightbox_attributes( $attachment_id )returns the attributes for an<a>: anhrefto the full-size attachment,data-method-lightbox,data-method-lightbox-src/-width/-height/-alt,data-method-lightbox-srcsetwhen afullsrcset exists, andaria-haspopup="dialog". It returns an empty array when the attachment has no usable full-size image, and the block then renders as if the lightbox were off. Without the script, or in a browser without<dialog>, the link simply opens the uncropped image. - One dialog per page. Each block’s view script calls
initMethodLightbox(); the first call installs the behaviour and later calls return at once (window.methodLightboxLoaded), so any mix of lightbox blocks shares a single lazily built<dialog class="method-lightbox">with anaria-label, a 44×44px close button and a<figure>for the image. - One delegated click listener handles
[data-method-lightbox]. Modifier and middle clicks keep their native behaviour (the image opens in a new tab); clicks Swiper has already cancelled after a drag are ignored, so swiping a gallery never opens it. - Native dialog semantics.
showModal()gives focus trapping, Escape to close, inert page content and focus restoration for free. The page is scroll-locked withhtml.method-lightbox-open; clicking anything but the image closes; the image getssizes="100vw"plus the full srcset so the browser picks a viewport-sized candidate; anis-loadingspinner shows until the image settles (skipped when it is already cached).
Using it in a block
A block wraps its image in the trigger and bundles the shared script into its own view script:
render callback
// render callback, as the Fitted Image block does it
$lightbox = $image_id ? method_get_lightbox_attributes( $image_id ) : array();
$open = '<div ' . get_block_wrapper_attributes( array( 'class' => 'my-block', 'id' => $methodId ) ) . '>';
$close = '</div>';
if ( $lightbox ) {
// The whole block becomes the trigger: an <a> to the full-size image.
$open = '<a ' . get_block_wrapper_attributes( array_merge(
array( 'class' => 'my-block method-lightbox-trigger', 'id' => $methodId ),
$lightbox
) ) . '>';
$close = '</a>';
}
frontend.js
// view script
import { initMethodLightbox } from '../../utils/lightbox';
initMethodLightbox();
The Fitted Image block does this when its lightbox attribute is on, wrapping the whole block in the trigger instead of a <div> and using the full-size version of whichever image rendered (the chosen image or the post thumbnail). The Swiper Gallery renders each .method-swiper-gallery-item as the trigger.
Styles
.method-lightbox-trigger— zoom-in cursor.dialog.method-lightbox— resets the UA dialog box to cover the viewport (100dvhwhere supported) with a 92% black surround; the image is letterboxed withobject-fit: contain..method-lightboxclose button and spinner; the image fade and spinner speed respectprefers-reduced-motion.
Changelog
| Version | Description |
|---|---|
| 2.0.0-beta23 | Introduced with the Fitted Image lightbox option and the rebuilt Swiper Gallery: method_get_lightbox_attributes(), lib/blocks/utils/lightbox.js, the shared dialog and styles (eacd345). |