{"id":71122,"date":"2021-10-26T02:25:00","date_gmt":"2021-10-25T15:25:00","guid":{"rendered":"https:\/\/elements.blog-cms.envato.net\/?p=39337"},"modified":"2025-11-11T17:48:23","modified_gmt":"2025-11-11T06:48:23","slug":"how-to-build-a-responsive-bootstrap-lightbox-gallery","status":"publish","type":"post","link":"https:\/\/elements.envato.com\/learn\/how-to-build-a-responsive-bootstrap-lightbox-gallery","title":{"rendered":"How to Build a Responsive Bootstrap Lightbox Gallery"},"content":{"rendered":"\n<p>How many times have you needed to add a responsive lightbox gallery to a Bootstrap project? In such a situation you might have tried an external JavaScript plugin like <a href=\"https:\/\/photoswipe.com\/\" target=\"_self\" rel=\"noopener\">PhotoSwipe<\/a>. However, you can create a simple yet fully functional responsive lightbox gallery by taking advantage of existing Bootstrap components. This tutorial will show you how to achieve this with minimal effort.<\/p>\n\n\n\n<p>Although not required, good knowledge of Bootstrap will be beneficial to follow along with this tutorial.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Our Responsive Bootstrap Lightbox Extension<\/h2>\n\n\n\n<p>Without further ado, here\u2019s what we\u2019ll be creating (click an image to open the lightbox):<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/codepen.io\/tutsplus\/pen\/mdMWeKr\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"1024\" height=\"723\" src=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox-1024x723.jpg\" alt=\"lightbox demo\" class=\"wp-image-85178\" srcset=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox-1024x723.jpg 1024w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox-300x212.jpg 300w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox-768x542.jpg 768w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox.jpg 1100w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Get Thousands of Bootstrap Templates on Envato Elements<\/h2>\n\n\n\n<p>Check out Envato Elements for a huge <a href=\"https:\/\/elements.envato.com\/web-templates\/bootstrap\" target=\"_self\" rel=\"noopener\">collection of Bootstrap templates<\/a>, website designs, and Bootstrap-based WordPress themes\u2014unlimited downloads with your monthly subscription!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/elements.envato.com\/web-templates\/bootstrap\"><img decoding=\"async\" width=\"850\" height=\"380\" src=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/bootstap-templates.jpg\" alt=\"envato elements\" class=\"wp-image-85095\" srcset=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/bootstap-templates.jpg 850w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/bootstap-templates-300x134.jpg 300w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/bootstap-templates-768x343.jpg 768w\" sizes=\"(max-width: 850px) 100vw, 850px\" \/><\/a><figcaption class=\"wp-element-caption\"><a rel=\"noopener\" href=\"https:\/\/elements.envato.com\/web-templates\/bootstrap\" target=\"_blank\">Premium Bootstrap templates<\/a> with your Envato Elements subscription<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">1. Define the HTML Markup<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Create an Image Grid<\/h3>\n\n\n\n<p>To begin with, we\u2019ll create an image grid to reveal the beauty of Ireland through some <a href=\"https:\/\/unsplash.com\/\" target=\"_blank\" rel=\"noopener\">Unsplash<\/a> images. To do this, we\u2019ll take advantage of <a href=\"https:\/\/getbootstrap.com\/docs\/5.1\/layout\/grid\/\" target=\"_blank\" rel=\"noopener\">Bootstrap\u2019s grid system<\/a>.<\/p>\n\n\n\n<p>All images should have the same dimensions. In our case, we\u2019ll work with big ones (1920px x 1280px). These will appear as soon as the lightbox opens.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"830\" height=\"586\" src=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/image_grid2.jpg\" alt=\"image grid\" class=\"wp-image-85096\" srcset=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/image_grid2.jpg 830w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/image_grid2-300x212.jpg 300w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/image_grid2-768x542.jpg 768w\" sizes=\"(max-width: 830px) 100vw, 830px\" \/><\/figure>\n\n\n\n<p>Here\u2019s the required structure for our grid:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;section class=\"image-grid\"&gt;\n  &lt;div class=\"container-xxl\"&gt;\n    &lt;div class=\"row gy-4\"&gt;\n      &lt;div class=\"col-12 col-sm-6 col-md-4\"&gt;\n        &lt;figure&gt;\n          &lt;a class=\"d-block\" href=\"\"&gt;\n            &lt;img width=\"1920\" height=\"1280\" src=\"ireland1.jpg\" class=\"img-fluid\" alt=\"Ring of Kerry, County Kerry, Ireland\" data-caption=\"Ring of Kerry, County Kerry, Ireland\"&gt;\n          &lt;\/a&gt;\n        &lt;\/figure&gt;\n      &lt;\/div&gt;\n      &lt;div class=\"col-12 col-sm-6 col-md-4\"&gt;\n        &lt;figure&gt;\n          &lt;a class=\"d-block\" href=\"\"&gt;\n            &lt;img width=\"1920\" height=\"1280\" src=\"ireland2.jpg\" class=\"img-fluid\" alt=\"Fintown, Ireland\" data-caption=\"Fintown, Ireland\"&gt;\n          &lt;\/a&gt;\n        &lt;\/figure&gt;\n      &lt;\/div&gt;\n      &lt;!-- more columns here --&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/section&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Build the Modal Skeleton<\/h3>\n\n\n\n<p>We\u2019ll continue by specifying a part of the markup needed for registering a <a href=\"https:\/\/getbootstrap.com\/docs\/5.1\/components\/modal\/#fullscreen-modal\" target=\"_blank\" rel=\"noopener\">full-screen Bootstrap modal<\/a>. Its main content will be created dynamically and hold a Bootstrap carousel.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div class=\"modal lightbox-modal\" tabindex=\"-1\"&gt;\n  &lt;div class=\"modal-dialog modal-fullscreen\"&gt;\n    &lt;div class=\"modal-content\"&gt;\n      &lt;button type=\"button\" class=\"btn-close btn-close-white\" data-bs-dismiss=\"modal\" aria-label=\"Close\"&gt;&lt;\/button&gt;\n      &lt;div class=\"modal-body\"&gt;\n        &lt;div class=\"container-fluid p-0\"&gt;\n          &lt;!-- JS content here --&gt;\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2. Add Some Styles<\/h2>\n\n\n\n<p>Coming up next, we\u2019ll add some styles for our project.<\/p>\n\n\n\n<p>Most importantly:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The Bootstrap lightbox images will have a maximum height equal to the viewport height. Additionally, we\u2019ll set their width to <code>auto<\/code>.<\/li>\n\n\n\n<li>The carousel controls will be vertically centered, and their height won\u2019t be equal to the carousel height (as happens by default with Bootstrap carousels). We do this because there will be an extra <strong>close<\/strong> button on the top right of the lightbox.<\/li>\n<\/ul>\n\n\n\n<p>Here are the associated styles:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* BASIC STYLES\n\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013 *\/\n:root {\n  --lightbox: #242424;\n}\n\nbody {\n  margin: 24px 0 48px;\n  font: 20px \/ 28px \"Marck Script\", cursive;\n}\n\n\/* IMAGE GRID STYLES\n\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013 *\/\n.image-grid figure {\n  margin-bottom: 0;\n}\n\n.image-grid img {\n  box-shadow: 0 1rem 1rem rgba(0, 0, 0, 0.15);\n  transition: box-shadow 0.2s;\n}\n\n.image-grid a:hover img {\n  box-shadow: 0 1rem 1rem rgba(0, 0, 0, 0.35);\n}\n\n\/* LIGHTBOX STYLES\n\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013 *\/\n.lightbox-modal .modal-content {\n  background: var(--lightbox);\n}\n\n.lightbox-modal .btn-close {\n  position: absolute;\n  top: 20px;\n  right: 18px;\n  font-size: 1.2rem;\n  z-index: 10;\n}\n\n.lightbox-modal .modal-body {\n  display: flex;\n  align-items: center;\n  padding: 0;\n  text-align: center;\n}\n\n.lightbox-modal img {\n  width: auto;\n  max-height: 100vh;\n  max-width: 100%;\n}\n\n.lightbox-modal .carousel-caption {\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background: rgba(36, 36, 36, 0.75);\n}\n\n.lightbox-modal .carousel-control-prev,\n.lightbox-modal .carousel-control-next {\n  top: 50%;\n  bottom: auto;\n  transform: translateY(-50%);\n  width: auto;\n}\n\n.lightbox-modal .carousel-control-prev {\n  left: 10px;\n}\n\n.lightbox-modal .carousel-control-next {\n  right: 10px;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3. Create the Bootstrap Lightbox<\/h2>\n\n\n\n<p>Each time we click on a link, the modal will appear and contain a carousel. By combining the modal and carousel Bootstrap components, we can produce a solid lightbox gallery that will be responsive and support swipe and keyboard navigations.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"850\" height=\"278\" src=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/lightbox_markup.jpg\" alt=\"html for lightbox\" class=\"wp-image-85097\" srcset=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/lightbox_markup.jpg 850w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/lightbox_markup-300x98.jpg 300w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/lightbox_markup-768x251.jpg 768w\" sizes=\"(max-width: 850px) 100vw, 850px\" \/><\/figure>\n\n\n\n<p>Here are some things for consideration:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>We\u2019ll generate the carousel markup only the very first time someone clicks on a link.<\/li>\n\n\n\n<li>Every other time, there\u2019s no need to recreate it and perform unnecessary actions. At that point, we\u2019ll only need to use the carousel\u2019s <a href=\"https:\/\/getbootstrap.com\/docs\/5.1\/components\/carousel\/#methods\" target=\"_blank\" rel=\"noopener\"><code>to()<\/code><\/a> method for navigating directly to the appropriate slide.<\/li>\n\n\n\n<li>The carousel won\u2019t autoplay, and its slides will change with a fade animation.<\/li>\n\n\n\n<li>Each slide will have an optional caption that will be determined by the <code>data-caption<\/code> attribute of the associated image. If an image doesn\u2019t need a caption on the lightbox, just don\u2019t place such an attribute. Note that we use a custom attribute instead of the default <code>alt<\/code> one for the image caption. The reason is that the first one is optional and might contain more detailed text compared to the second one, which is always good to have for accessibility reasons. But you\u2019re free to customize this behavior if you want.<\/li>\n\n\n\n<li>The carousel images won\u2019t contain the <code>d-block<\/code> and <code>w-100<\/code> classes that exist on all Bootstrap code examples.<\/li>\n<\/ul>\n\n\n\n<p>With all the above in mind, here\u2019s the associated JavaScript code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const imageGrid = document.querySelector(\".image-grid\");\nconst links = imageGrid.querySelectorAll(\"a\");\nconst imgs = imageGrid.querySelectorAll(\"img\");\nconst lightboxModal = document.getElementById(\"lightbox-modal\");\nconst bsModal = new bootstrap.Modal(lightboxModal);\nconst modalBody = document.querySelector(\".modal-body .container-fluid\");\n\nfor (const link of links) {\n  link.addEventListener(\"click\", function (e) {\n    e.preventDefault();\n    const currentImg = link.querySelector(\"img\");\n    const lightboxCarousel = document.getElementById(\"lightboxCarousel\");\n    if (lightboxCarousel) {\n      const parentCol = link.parentElement.parentElement;\n      const index = &#091;...parentCol.parentElement.children].indexOf(parentCol);\n      const bsCarousel = new bootstrap.Carousel(lightboxCarousel);\n      bsCarousel.to(index);\n    } else {\n      createCarousel(currentImg);\n    }\n    bsModal.show();\n  });\n}\n\nfunction createCarousel(img) {\n  const markup = `\n    &lt;div class=\"carousel slide carousel-fade\" data-bs-ride=\"carousel\" data-bs-interval=\"false\"&gt;\n      &lt;div class=\"carousel-inner\"&gt;\n        ${createSlides(img)}\n      &lt;\/div&gt; \n      &lt;button class=\"carousel-control-prev\" type=\"button\" data-bs-target=\"#lightboxCarousel\" data-bs-slide=\"prev\"&gt;\n       &lt;span class=\"carousel-control-prev-icon\" aria-hidden=\"true\"&gt;&lt;\/span&gt;\n       &lt;span class=\"visually-hidden\"&gt;Previous&lt;\/span&gt;\n      &lt;\/button&gt;\n      &lt;button class=\"carousel-control-next\" type=\"button\" data-bs-target=\"#lightboxCarousel\" data-bs-slide=\"next\"&gt;\n        &lt;span class=\"carousel-control-next-icon\" aria-hidden=\"true\"&gt;&lt;\/span&gt;\n        &lt;span class=\"visually-hidden\"&gt;Next&lt;\/span&gt;\n      &lt;\/button&gt;\n    &lt;\/div&gt;\n    `;\n\n  modalBody.innerHTML = markup;\n}\n\nfunction createSlides(img) {\n  let markup = \"\";\n  const currentImgSrc = img.getAttribute(\"src\");\n\n  for (const img of imgs) {\n    const imgSrc = img.getAttribute(\"src\");\n    const imgAlt = img.getAttribute(\"alt\");\n    const imgCaption = img.getAttribute(\"data-caption\");\n\n    markup += `\n    &lt;div class=\"carousel-item${currentImgSrc === imgSrc ? \" active\" : \"\"}\"&gt;\n      &lt;img src=${imgSrc} alt=${imgAlt}&gt;\n      ${imgCaption ? createCaption(imgCaption) : \"\"}\n    &lt;\/div&gt;\n    `;\n  }\n\n  return markup;\n}\n\nfunction createCaption(caption) {\n  return `&lt;div class=\"carousel-caption\"&gt;\n     &lt;p class=\"m-0\"&gt;${caption}&lt;\/p&gt;\n    &lt;\/div&gt;`;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Our Responsive Bootstrap Lightbox Is Complete!<\/h2>\n\n\n\n<p>That concludes another Bootstrap customization! During this short journey, we first built an image grid and then covered the creation of a responsive lightbox gallery. Crucially, we created this lightbox by only slightly customizing existing Bootstrap components. I hope this has inspired you to create even more powerful Bootstrap lightboxes.<\/p>\n\n\n\n<p>For optimal results, be sure to use images with equal dimensions, or else you\u2019ll notice a small jump when the active slide changes.<\/p>\n\n\n\n<p>Once again, here\u2019s what we built:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/codepen.io\/tutsplus\/pen\/mdMWeKr\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"1024\" height=\"723\" src=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox-1-1024x723.jpg\" alt=\"codepen demo\" class=\"wp-image-85179\" srcset=\"https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox-1-1024x723.jpg 1024w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox-1-300x212.jpg 300w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox-1-768x542.jpg 768w, https:\/\/elements.envato.com\/learn\/wp-content\/uploads\/2023\/12\/codepen-lightbox-1.jpg 1100w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>If you want to go even further and familiarize yourselves with building custom lightboxes, have a look at another recent <a href=\"https:\/\/webdesign.tutsplus.com\/draggable-javascript-image-gallery-with-gsap--cms-37591t\" target=\"_blank\" rel=\"noopener\">tutorial<\/a>.<\/p>\n\n\n\n<p>As always, thanks a lot for reading!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Learn to Customize Bootstrap Yourself<\/h2>\n\n\n\n<p>We\u2019ve covered a lot of Bootstrap customizations over the years; take a look yourself!<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/webdesign.tutsplus.com\/bootstrap-carousel-indicators-into-progress-bars--cms-37536t\" target=\"_blank\" rel=\"noreferrer noopener\">How to Convert Bootstrap Carousel Indicators Into Animated Progress Bars<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/webdesign.tutsplus.com\/convert-bootstrap-pills-tabs-into-a-dropdown-menu--cms-35817t\" target=\"_blank\" rel=\"noreferrer noopener\">How to Convert Bootstrap Pills (Tabs) Into a Dropdown Menu<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/webdesign.tutsplus.com\/how-to-customize-bootstraps-4-accordion-component--cms-32510t\" target=\"_blank\" rel=\"noreferrer noopener\">Quick Tip: How to Customize Bootstrap 4\u2019s Accordion Component<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/webdesign.tutsplus.com\/how-to-make-the-bootstrap-navbar-dropdown-work-on-hover--cms-33840t\" target=\"_blank\" rel=\"noreferrer noopener\">How to Make the Bootstrap Navbar Dropdown Work on Hover<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Today, we\u2019ll build something that I\u2019m sure many of you wish was integrated into Bootstrap by default: a responsive lightbox gallery.<\/p>\n","protected":false},"author":192,"featured_media":85098,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[207],"tags":[],"class_list":["post-71122","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-design"],"acf":[],"_links":{"self":[{"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/posts\/71122","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/users\/192"}],"replies":[{"embeddable":true,"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/comments?post=71122"}],"version-history":[{"count":0,"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/posts\/71122\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/media\/85098"}],"wp:attachment":[{"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/media?parent=71122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/categories?post=71122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/elements.envato.com\/learn\/wp-json\/wp\/v2\/tags?post=71122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}