How to add lightbox to WordPress images and galleries without plugin


When it comes to adding a lightbox effect to WordPress images and galleries, the options may seem overwhelming. Many plugins are available, but they often come with unnecessary complexities and code. To simplify the process for your clients, a great solution is to integrate lightbox functionality directly into the WordPress core images and galleries. I will walk you through the complete steps to achieve a lightweight and easy-to-use lightbox for your WordPress theme.

To start, we’ll register a custom block style that will allow your clients to easily apply the lightbox effect to images and galleries.

Example of registering block style

function theme_name_register_block_styles() {
register_block_style( 
		'core/image',
		array(
			'name'  => 'lightbox',
			'label' => __( 'Lightbox', 'theme_name' ),
		)
	);

	register_block_style( 
		'core/gallery',
		array(
			'name'  => 'lightbox',
			'label' => __( 'Lightbox', 'theme_name' ),
		)
	);
add_action( 'init', 'theme_name_register_block_styles' );

Example of JavaScript file.

document.addEventListener('DOMContentLoaded', function() {
  // Get all lightbox containers by class name
  var lightboxContainers = document.getElementsByClassName('is-style-lightbox');

  // Loop through each lightbox container
  Array.from(lightboxContainers).forEach(function(container) {
    // Find all child images within the container
    var images = container.querySelectorAll('img');

    // Loop through each image
    Array.from(images).forEach(function(image, index) {
      // Add the lightbox image class
      image.classList.add('lightbox-image');

      // Add click event listener to open lightbox
      image.addEventListener('click', function() {
        openLightbox(container, images, index);
      });
      

  
    });
  });

  // Function to open lightbox
  function openLightbox(container, images, startIndex) {
    // Create the lightbox overlay and content elements
    var overlay = document.createElement('div');
    overlay.classList.add('lightbox-overlay');

    var content = document.createElement('div');
    content.classList.add('lightbox-content');

    // Create the close button element
    var closeButton = document.createElement('span');
    closeButton.classList.add('lightbox-close');
    closeButton.innerHTML = '×';

    // Add click event listener to close lightbox
    closeButton.addEventListener('click', function() {
      closeLightbox(container, overlay);
    });

    // Append the close button to the content element
    content.appendChild(closeButton);

    // Create the navigation arrows
    var prevArrow = document.createElement('span');
    prevArrow.classList.add('lightbox-arrow', 'lightbox-arrow-prev');
    prevArrow.innerHTML = '❮';

    var nextArrow = document.createElement('span');
    nextArrow.classList.add('lightbox-arrow', 'lightbox-arrow-next');
    nextArrow.innerHTML = '❯';

    // Check if there is more than one image
    if (images.length > 1) {
      // Add click event listeners to navigate between images
      prevArrow.addEventListener('click', function() {
        showPreviousImage();
      });

      nextArrow.addEventListener('click', function() {
        showNextImage();
      });

      // Append the navigation arrows to the content element
      content.appendChild(prevArrow);
      content.appendChild(nextArrow);
    }

    // Create the container for the images
    var imageContainer = document.createElement('div');
    imageContainer.classList.add('lightbox-image-container');

    // Loop through each image and clone them
    Array.from(images).forEach(function(image, index) {
      // Clone the image and add additional classes
      var clonedImage = image.cloneNode(true);
      clonedImage.classList.add('lightbox-enlarged');
      clonedImage.style.display = 'none'; // Hide all images initially except for the selected one

      // Append the cloned image to the container
      imageContainer.appendChild(clonedImage);

      // Show the selected image
      if (index === startIndex) {
        clonedImage.style.display = 'block';
        clonedImage.style.animation = 'tilt 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both';
      }
    });

    // Append the image container to the content element
    content.appendChild(imageContainer);

    // Append the content element to the overlay element
    overlay.appendChild(content);

    // Append the overlay to the body
    document.body.appendChild(overlay);

    // Add click event listener to close lightbox when clicking outside the image
    overlay.addEventListener('click', function(event) {
      if (event.target === overlay) {
        closeLightbox(container, overlay);
      }
    });

    // Variable to keep track of the current image index
    var currentIndex = startIndex;

    // Function to show the next image
    function showNextImage() {
      var nextIndex = (currentIndex + 1) % images.length;
      imageContainer.children[currentIndex].style.display = 'none';
      imageContainer.children[nextIndex].style.display = 'block';
      imageContainer.children[nextIndex].style.animation = 'tilt 0.6s cubic-bezier(0.680, -0.550, 0.265, 1.550) both';

      currentIndex = nextIndex;
    }

    // Function to show the previous image
    function showPreviousImage() {
      var previousIndex = (currentIndex - 1 + images.length) % images.length;
      imageContainer.children[currentIndex].style.display = 'none';
      imageContainer.children[previousIndex].style.display = 'block';
      imageContainer.children[previousIndex].style.animation = 'tilt-back 0.6s cubic-bezier(0.680, -0.550, 0.265, 1.550) both';
      currentIndex = previousIndex;
    }

    // Add keyboard arrow key support for sliding
    document.addEventListener('keydown', function(event) {
      if (event.key === 'ArrowRight') {
        showNextImage();
      } else if (event.key === 'ArrowLeft') {
        showPreviousImage();
      } else if (event.key === 'Escape') {
        closeLightbox(container, overlay);
      }
    });

    // Lazy load images within the lightbox
    var lazyImages = overlay.querySelectorAll('img[data-src]');
    Array.from(lazyImages).forEach(function(lazyImage) {
      lazyImage.setAttribute('src', lazyImage.getAttribute('data-src'));
      lazyImage.onload = function() {
        lazyImage.removeAttribute('data-src');
      };
    });

    // Show caption if available
    var caption = images[startIndex].getAttribute('alt');
    if (caption) {
      var captionElement = document.createElement('div');
      captionElement.classList.add('lightbox-caption');
      captionElement.innerText = caption;
      content.appendChild(captionElement);
    }
  }

  // Function to close lightbox
  function closeLightbox(container, overlay) {
    // Remove the overlay from the body
    document.body.removeChild(overlay);

    
  }
});

Example of wp_enqueue_script() assuming that you will create in that location file named like this:

wp_enqueue_script('lightbox', get_template_directory_uri() . '/assets/js/lightbox.js', array('jquery'), '1.0', true);

Example of CSS

.lightbox-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.8);
  z-index: 9999;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: opacity 0.3s ease;
}

/* Lightbox content */
.lightbox-content {
  position: relative;
  margin: auto;
  padding: 0;
  width: 90%;
}

.lightbox-close {
  position: absolute;
  font-size: 48px;
  font-weight: bold;
  top: 10px;
  right: 10px;
  color: var(--wp--preset--color--primary-light);
  cursor: pointer;
  transition: color 0.3s ease;
  z-index: 1;
}

.lightbox-close:hover {
  color: var(--wp--preset--color--primary);
}

.lightbox-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  font-size: 48px;
  color: var(--wp--preset--color--primary-light);
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 0.3s ease;
  z-index: 1;
}

.lightbox-arrow:hover {
  opacity: 1;
}

.lightbox-arrow-prev {
  left: 10px;
}

.lightbox-arrow-next {
  right: 10px;
}

.lightbox-image-container {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 90vh;
  padding: 1.6rem;
  margin: auto;
}

/* Lightbox image */
.lightbox-image {
  cursor: pointer;
  transition: opacity 0.2s;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.lightbox-image:hover {
  opacity: 0.7;
}

.lightbox-enlarged {
  opacity: 1;
}

.lightbox-caption {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  margin: auto;
  padding: 1rem;
  text-align: center;
  background-color: rgba(0, 0, 0, 0.8);
  color: var(--wp--preset--color--primary-light);
  border-radius: 24px;
}

 @-webkit-keyframes tilt{
              0% {
                -webkit-transform: rotateY(20deg) rotateX(35deg) translate(300px, -300px) skew(-35deg, 10deg);
                        transform: rotateY(20deg) rotateX(35deg) translate(300px, -300px) skew(-35deg, 10deg);
                opacity: 0;
              }
              
              100% {
                -webkit-transform: rotateY(0) rotateX(0deg) translate(0, 0) skew(0deg, 0deg);
                        transform: rotateY(0) rotateX(0deg) translate(0, 0) skew(0deg, 0deg);
                opacity: 1;
              }
            }
            @keyframes tilt {
              0% {
                -webkit-transform: rotateY(20deg) rotateX(35deg) translate(300px, -300px) skew(-35deg, 10deg);
                        transform: rotateY(20deg) rotateX(35deg) translate(300px, -300px) skew(-35deg, 10deg);
                opacity: 0;
              }
				
              100% {
                -webkit-transform: rotateY(0) rotateX(0deg) translate(0, 0) skew(0deg, 0deg);
                        transform: rotateY(0) rotateX(0deg) translate(0, 0) skew(0deg, 0deg);
                opacity: 1;
              }
            }

            @-webkit-keyframes tilt-back {
              0% {
                -webkit-transform: rotateY(-20deg) rotateX(35deg) translate(-300px, -300px) skew(35deg, -10deg);
                        transform: rotateY(-20deg) rotateX(35deg) translate(-300px, -300px) skew(35deg, -10deg);
                opacity: 0;
              }
				
              100% {
                -webkit-transform: rotateY(0) rotateX(0deg) translate(0, 0) skew(0deg, 0deg);
                        transform: rotateY(0) rotateX(0deg) translate(0, 0) skew(0deg, 0deg);
                opacity: 1;
              }
            }
            @keyframes tilt-back {
              0% {
                -webkit-transform: rotateY(-20deg) rotateX(35deg) translate(-300px, -300px) skew(35deg, -10deg);
                        transform: rotateY(-20deg) rotateX(35deg) translate(-300px, -300px) skew(35deg, -10deg);
                opacity: 0;
              }
				
              100% {
                -webkit-transform: rotateY(0) rotateX(0deg) translate(0, 0) skew(0deg, 0deg);
                        transform: rotateY(0) rotateX(0deg) translate(0, 0) skew(0deg, 0deg);
                opacity: 1;
              }
            }

You can see lightbox in action on this website