Views Lightbox (VVJL) renders a Views row set as an accessible, keyboard-navigable image lightbox gallery — grid thumbnails that open into a modal — using pure vanilla JavaScript with no jQuery. It requires Drupal 11.3 or 12, and it is free on drupal.org.
What it does
VVJL adds a Lightbox display style to Views: select it in the Format section and a row-style view renders as a responsive image grid where clicking any item opens a modal viewer with navigation between items, rather than linking away to a full page or a separate image. It is a Views style plugin, not a field formatter, so it applies to the whole view's row output rather than one field at a time.
Requirements
| Requirement | Value |
|---|---|
| Drupal core | ^11.3 || ^12 |
| PHP | 8.3+ |
| Core modules | Views, Filter |
| Required contrib module | VVJ Core (vvj_core) — not optional |
VVJL depends on VVJ Core and will not install without it. VVJ Core supplies the shared style-plugin base class, the accessibility helpers, and the JavaScript custom-element foundation every VVJ v2 module builds on — it does nothing on its own. Composer resolves it for you:
composer require drupal/vvjl:^2.0
Installing from a downloaded tarball instead of Composer means downloading vvj_core yourself and enabling it first — the admin modules page will refuse to enable VVJL without it on disk.
This is a Drupal 11.3+ and 12 module, not Drupal 10. VVJL 2.x is built on Views' current #[ViewsStyle] attribute-based plugin discovery, which is what Drupal 12 requires — annotation-only plugin discovery was removed in Drupal 12. If you need this on a Drupal 10 site, that means upgrading first; Drupal 10 to 11/12 upgrades are work I do.
Setting up the view
| Requirement | Detail |
|---|---|
| First field | An image field, and it should not be set clickable — the module opens the modal itself and disables a clickable image link as a fallback if you forget, but leaving it non-clickable avoids relying on that fallback |
| Remaining fields | Positioned at the bottom of each grid image as caption content |
| Images per item | One image per row for the lightbox itself; any links in the remaining fields stay active inside the opened modal |
| CSS classes | vvj-lightbox on the view, alongside Views' own js-view-dom-id; a grid-count-N class carrying the item count |
| Not supported | Views' "Grouping Field" option — leave it off |
Configuration options
- Grid image width and gap — set in pixels, controlling the thumbnail grid layout.
- Overlay color and opacity, with an option to disable the modal overlay entirely.
- Animation type for the transition between images — top, bottom, left, right, or zoom.
Accessibility
Accessibility is not a bolt-on here — it is why the module exists in its current form. VVJL ships:
- ARIA roles and properties
- The modal and its controls carry the roles and state attributes a screen reader needs to announce what is open and what changed.
- Keyboard navigation
- Every action available with a mouse — opening an item, moving to the next or previous image, closing the modal — is reachable from the keyboard.
- Focus management
- Opening the modal moves focus into it, and the currently displayed item stays focused as you navigate, rather than leaving keyboard focus stranded on the page behind the overlay.
All of the lightbox's interactive controls are inline SVG, so if you need a different accent color, target the SVG fill directly rather than swapping icon assets.
Custom tokens for Views header and footer
Views' built-in "Use replacement tokens from the first row" option on a Global: Text area or Global: Unfiltered text field does not resolve against Lightbox output. Use VVJL's own tokens instead:
[vvjl:title]- Replaces the default
{{ title }}token. [vvjl:field_image]- Replaces
{{ field_image }}, and the same pattern works for any other field machine name. [vvjl:title:plain]- Append
:plainto strip HTML from the resolved value.
A field using a complex rewrite (Global: Custom text with its own {{ tokens }}) is not supported — use the individual field token form. Token resolution runs through the shared vvj_core.token_resolver service in v2, but the token syntax itself is unchanged from 1.x.
Targeting the markup with CSS
To style the fields inside the closed grid, target .vvjl-inner > .lightbox-row .lightbox-image. To style the same fields once the modal is open, target .vvjl-inner > .lightbox-modal .lightbox-image instead — the grid and the modal use separate markup, not the same nodes repositioned.
Installation
composer require drupal/vvjl:^2.0
drush en vvjl -y
drush cr
Then edit or create a view, and in the Format section choose Lightbox as the display style.
Common questions
What happens if I leave the first field clickable by mistake?
VVJL includes a fallback that disables the click behaviour on that field so the modal still opens correctly, but the cleaner setup is to leave the first field non-clickable from the start and let the module own the click.
Can a gallery item link to more than one image in the modal?
Only one image per row feeds the lightbox itself. Any additional links in the row's other fields remain clickable inside the opened modal, but they are not additional lightbox images.
Does the Grouping Field option in Views work with this display style?
No. This is a stated limitation of the current implementation — avoid it for any view using the Lightbox style.
Is this compatible with Drupal 10?
No. core_version_requirement is ^11.3 || ^12. A Drupal 10 site needs the 1.x branch or a core upgrade first.
Does the lightbox require jQuery or a JavaScript gallery library?
No. It is built entirely in vanilla JavaScript, coordinated through the shared vvj_core custom-element foundation — no jQuery, no third-party lightbox library.
Related VVJ display formats
For a full-width banner instead of a gallery grid, see Views Hero. For a scroll-driven background treatment on the same row data, see Views Parallax. If your image galleries live inside Paragraphs rather than Views, Paragraphs Bundles ships comparable components as paragraph types.
Need a gallery built and tuned for a real project instead of configured yourself, or help clearing a Drupal 10 site for the Drupal 11/12 upgrade this module requires? See my Drupal services or get in touch.