Turn WordPress Image & Gallery Blocks into a Lightbox

viewing an image gallery

Turn any standard WordPress image or gallery block into a fully responsive lightbox, with swipe left/right and full-screen mode. There’s only a minimal amount of copy-and-paste code, and it’s a great way to enhance your WordPress site without having to install yet another plugin.

By default, when you add a gallery or image block to WordPress content and set “Link To” media file… when someone clicks on the image in the frontend it will open the image, and the viewer has to click the back button to get back to your site/content. It’s a bit… old-fashioned.

A ligithbox tidies this up by making the navigation much more intuitive, especially on mobile devices. Try it out on this gallery to see the lightbox in action.

Before starting this tutorial, make sure that you’re using a custom child theme so we can add some code to functions.php.

infoUpdated 27th January 2022 to handle the new gallery block HTML in WordPress 5.9.

infoUpdated 11th July 2023 to include version 3.4.1 of FSLightbox and a couple of new global configuration options.

tipIf you use Headwall Hosting to host your WordPress website, you don’t need this tutorial at all, you can just activate the Auto-Lightbox function form WP Admin Dashboard

auto-lightbox switch
Auto-Lightbox Option

The Logic

For this tutorial, The logic for our little theme-extension is nice and simple:

  • When our website loads a page, enqueue our asset files:
    • The fslightbox.js JavaScript library
    • A bit of our own JavaScript to link it together.
  • When the page has loaded in the browser, run our JavaScript
    • Scan the page looking for image blocks and gallery blocks, where the images are linked to the source media files.
    • Modify these blocks (they’re just <div> elements) so they’ve got the necessary markup for fslightbox.js to work.
  • Initialise fslightbox.js

Nice and simple. Simple is good 😎

The Code

In your custom child theme’s main folder, create an empty file called “wpt-lightbox.php” and a new folder called “wpt-lightbox“. In this folder, create a new/empty text file called “wpt-lightbox-frontend.js“. We’ll put some code in there later – for now, it just needs to exist.

Next, download the latest version of fslightbox.js. There’s a basic/free version and a paid-for/Pro version. The basic version will work fine for this website, but you can use the Pro version if you want the extra features.

Extract the zip file and copy “fslightbox.js” into the “wpt-lightbox” folder in your custom child theme. Your custom child theme’s directory layout should now look something like this:

  • my-custom-child-theme/
    • functions.php
    • style.css
    • wpt-lightbox/
      • fslightbox.js
      • wpt-lightbox-frontend.js
    • wpt-lightbox.php

The PHP Bit

Edit wpt-lightbox.php and paste the following into it – this will catch when WordPress is rendering the page headers and insert our two JavaScript files into it.

<?php

/*
 * WP Tutorials :: Lightbox (WPTL)
 *
 * https://wp-tutorials.tech/refine-wordpress/turn-wordpress-image-gallery-blocks-into-responsive-lightbox/
 *
 * fslightbox.js : https://fslightbox.com/
 */

// Block direct access.
defined('WPINC') || die();

const WPTL_FSLIGHTBOX_VERSION = '3.4.1';
const WPTL_ONLY_ONE_LIGHTBOX_PER_PAGE = false; //true;
const WPTL_EXIT_FULL_SCREEN_ON_CLOSE = false; //true;

function wptl_enqueue_scripts() {
	$theme_version = wp_get_theme()->get('Version');
	$base_url = get_stylesheet_directory_uri() . '/' . pathinfo(__FILE__, PATHINFO_FILENAME) . '/';

	// The main fslightbox.js code.
	// null means it doesn't depend on any other scripts.
	// The last parameter (true) means it can be safely enqueued in the site's footer.
	// Better for page-load speed.
	wp_enqueue_script(
		'fslightbox',
		$base_url . 'fslightbox.js',
		null,
		WPTL_FSLIGHTBOX_VERSION,
		true
	);

	// Our custom code to initialise fslightbox.js
	// The array( 'lightbox' ) parameter tells WordPress that the fslightbox
	// script must be loaded before our wpt-lightbox-frontend script.
	wp_enqueue_script(
		'wpt-lightbox-frontend',
		$base_url . 'wpt-lightbox-frontend.js',
		array('fslightbox'),
		$theme_version
	);

	// Inject an inline script snippet into the HTML that defines a global
	// JavaScript object called "wptLightbox".
	wp_localize_script(
		'wpt-lightbox-frontend',
		'wptLightbox',
		array(
			'oneLightboxPerPage' => WPTL_ONLY_ONE_LIGHTBOX_PER_PAGE,
			'exitFullScreenOnClose' => WPTL_EXIT_FULL_SCREEN_ON_CLOSE,
		)
	);
}
add_action('wp_enqueue_scripts', 'wptl_enqueue_scripts');

This has been tested with FSLightBox 3.4.1. If you’re using a different/newer version, you should change the WPTL_FSLIGHTBOX_VERSION constant so it matches the version you’re using.

Now we need to pull-in the file to our theme. Open your child theme’s functions.php file and add the following:

// WP-Tutorials Gallery to Lightbox
require_once dirname(__FILE__) . '/wpt-lightbox.php';

Frontend JavaScript Bit

Open the file wpt-lightbox/wpt-lightbox-frontend.js and paste the following into it. The logic should be easy to follow just by going through the code.

/*
 * WP Tutorials :: Lightbox (WPTL)
 *
 * https://wp-tutorials.tech/refine-wordpress/turn-wordpress-image-gallery-blocks-into-responsive-lightbox/
 *
 * fslightbox.js : https://fslightbox.com/
 */


// When the document has finished loading...
document.addEventListener('DOMContentLoaded', function() {
	'use strict';

	// Diagnostics to show that our script has loaded correctly.
	// console.log('fslightbox : load');

	// console.log('typeof refreshFsLightbox' );

	if (typeof wptLightbox === 'undefined') {
		// ...
	} else if (typeof refreshFsLightbox !== 'function') {
		// ...
	} else {
		// Diagnostics to show that our script is about to initialise.
		// console.log('fslightbox : init');

		var lightboxImageCount = 0;

		// Scan the DOM for image blocks that have a link <a> element.
		var elements = document.querySelectorAll('.wp-block-image a');
		for (var index = 0; index < elements.length; ++index) {
			var element = elements[index];
			if (element.href) {
				element.setAttribute('data-fslightbox', `Image ${index + 1}`);
				++lightboxImageCount;
			}
		}

		// Scan the DOM for gallery blocks...
		var galleryElements = document.querySelectorAll('.wp-block-gallery');
		for (var galleryIndex = 0; galleryIndex < galleryElements.length; ++galleryIndex) {
			var galleryElement = galleryElements[galleryIndex];
			var galleryName = null

			// Each gallery on the page should have a unique name. If we only want
			// one lightbox for the entire page, we need to use the same gallery
			// name everywhere.
			if (wptLightbox.oneLightboxPerPage) {
				galleryName = 'Gallery';
			} else {
				galleryName = `Gallery ${galleryIndex + 1}`;
			}

			// Within the gallery, scan for images that have a link.
			elements = galleryElement.querySelectorAll('.wp-block-gallery > .wp-block-image > a');
			for (var index = 0; index < elements.length; ++index) {
				var element = elements[index];
				if (element.href) {
					element.setAttribute('data-fslightbox', galleryName);
					++lightboxImageCount;
				}
			}
		}

		// Only initialise fslightbox.js if we found one-or-more images with links.
		if (lightboxImageCount > 0) {
			console.log(`Lightbox images: ${lightboxImageCount} : Init FsLightbox now`);
			refreshFsLightbox();

			// After refreshFsLightbox() has created the global fsLightboxInstances
			// object, we can loop through each FS Lightbox instance and set
			// additional properties. More properties are here:
			// https://fslightbox.com/javascript/documentation/other-props
			Object.keys(fsLightboxInstances).forEach((instanceName) => {
				// Diagnostics
				// console.log(`Configure instance: ${instanceName}`);
				fsLightboxInstances[instanceName].props.exitFullscreenOnClose = wptLightbox.exitFullScreenOnClose;
			});
		}

	}
});

Save the file, and then… actually, that’s all there is to it.

Finish and Test

Find or create some content on your site and add a gallery. Add some images to the gallery, and set the gallery’s link-to property so that it should Link-to the Media File when an image is clicked-on. Choose whatever you want for the Image Size – it doesn’t need to be “Large” like it is here.

Save and test. Now… when you click on one of the images in your gallery, it should open up in a lightbox so you can swipe left/right to flick between the images.

WordPress gallery block : The Link-To property
Link To : Media File

Happy lightbox-ing 😎 👍

Like This Tutorial?

Let us know

WordPress plugins for developers

4 thoughts on “Turn WordPress Image & Gallery Blocks into a Lightbox”

  1. I was so frustrated with all the plugins and … and this is described so well. Made it really easy for me to implement. Thank you!

    I have to two question:
    1. In full screen mode, I would expect the closing button to simultaneously finish the full screen mode. By default, it only closes the lightbox. The documentation suggests to put “fsLightbox.props.exitFullscreenOnClose = true;” The closest I can find to match this is “u.exitFullscreenOnClose&&s.ifs&&c.x()”. How do I make this true?
    2. I would like to spread the images of an article throughout the text, but have them all displayed in one lightbox. Any hints?

    Cheers. Julia

    Reply
    • Hi Julia. I’ve made a couple of updates to the tutorial for you, based on your feedback.

      In wpt-lightbox.php, you’ll see two new constants at the top of the file, “WPTL_ONLY_ONE_LIGHTBOX_PER_PAGE” and “WPTL_EXIT_FULL_SCREEN_ON_CLOSE”. If you set these to true, you will get the behaviour you need.

      • By setting WPTL_ONLY_ONE_LIGHTBOX_PER_PAGE=true, we assign the same “galleryName” to every image we find, so refreshFsLightbox() creates one gallery instance.
      • There is a new block at the end of the JavaScript that loops through all FSLightBox instances and sets the exitFullscreenOnClose prop. You can set any props you want from here https://fslightbox.com/javascript/documentation/other-props

      I hope this helps

      Reply
      • Thanks for this quick and thorough solution.
        Assigning the same “galleryName” did put various galleries into one lightbox and put me on the right track, since I still needed to weave in single images as well. Now setting their attributes to “galleryName” as well, makes one lovely lightbox.

        Reply

Leave a comment