Table of Contents
Beautiful and fully responsive gallery can make your website stand out. And, if you use some front-end framework, you can get this done in a few minutes. This is what this tutorial will be about. We will use Foundation framework along with a few custom styles and JavaScript to create responsive gallery with reveal modals. In addition, you will have a chance to practice some features of ES6 such as arrow functions. Enjoy this tutorial on building responsive gallery with Foundation!
Live demo on CodePen.
Source code on GitHub.
Introduction
Welcome in another simple tutorial! The goal of this tutorial is building responsive gallery with custom modals. To achieve this, we will use Foundation framework and its grid system based on flexbox. If you have never used this framework, then this tutorial will be a gentle introduction. I wanted to make this responsive gallery tutorial as technology-neutral and portable as possible. As a result, we will not need to use many external resources. In a fact, we will need only one.
This resource will be Foundation and its flexbox grid system. In this tutorial, I used version hosted on CDN. If you want to use complete Foundation framework, you can download it from Foundation website. However, this is not necessary nor required. Also, there is one thing I want to mention before we get started this responsive gallery tutorial. We will use two plugins, autoprefixer and babel. Autoprefixer adds CSS vendor prefixes. Babel compiles ES6 syntax.
HTML
The first part of this responsive gallery tutorial is rests in creating html document. Since the content of head section will depend on your own project, we will include only the necessary tags. These tags will be title, stylesheet links, and meta tags for charset and viewport. As I mentioned above, we will use only one external CSS resource, Foundation framework. Another, and also the last, CSS resource will be main stylesheet.
HTML:
<head> <meta charset="utf-8"> <title>Responsive Gallery with Foundation</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.2.4/foundation-flex.min.css"> <link rel="stylesheet" href="styles/main.css"> </head>
Preparing the content for responsive gallery
The body of html document will consist of two pats. First will be gallery wrapper with individual images provided by Unsplash. These images are royalty-free. So, if you like some of them, you can use it. However, I would still recommend to give credit to a photographer. In this responsive gallery tutorial, we will mention every photographer in alt attributes of images. Every image will be wrapped inside anchor tag. Every tag will have data-toggle attribute with value of “galleryModal”. We will use this attribute later in JavaScript to find these tags.
HTML:
<!-- Gallery wrapper --> <div class="gallery-wrapper row expanded"> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/zZzKLzKP24o/600x600" alt="Photo by Caleb George" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/3YfSwCfJ6Do/600x600" alt="Photo by Garth Pratt" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/8Pd8yCjjKIQ/600x600" alt="Photo by Maxime Le Conte des Floris" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/2Bjq3A7rGn4/600x600" alt="Photo by Martin Jernberg" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/EDqP5r_QwrE/600x600" alt="Photo by Alec Weir" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/IEqPWQvnR1E/600x600" alt="Photo by Jaclyn Clark" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/4KgtxwMeLYw/600x600" alt="Photo by Andrew Collins" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/GnU2altkUSQ/600x600" alt="Photo by Clem Onojeghuo" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/Yfyt6q8gjaQ/600x600" alt="Photo by Clem Onojeghuo" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/8soQzdz9XXA/600x600" alt="Photo by Clem Onojeghuo" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/myFsTTkub9E/600x600" alt="Photo by Scott Webb" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/3kmDKoHY7as/600x600" alt="Photo by Matheus Ferrero" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/ZMRMFULofus/600x600" alt="Photo by Joel Filipe" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/n3FM6tfn9XQ/600x600" alt="Photo by Aaron Barnaby" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/SdEDmcrJOE4/600x600" alt="Photo by Geetanjal Khanna" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/6hC831t-ihM/600x600" alt="Photo by Anton Romanov" /> </a> </div> </div><!-- .end Gallery wrapper -->
Preparing the structure for reveal overlay and dialog
The second part of this responsive gallery tutorial related to html will be reveal overlay and reveal dialog (or modal). In addition, reveal dialog (modal) will also contain a number of components. We will need h2 heading for photo info and its author and img tag for preview image. Also, we will need a button to close the reveal dialog. Reveal dialog will be wrapped inside reveal overlay. I used plain div for reveal dialog. However, you can also use article element. Then, you can also use h1.
HTML:
<!-- Gallery overlay --> <div class="js-gallery-overlay gallery-overlay reveal-overlay"> <!-- Gallery modal --> <div class="js-gallery-reveal gallery-reveal reveal" id="galleryModal" data-reveal data-overlay="true"> <h2 class="js-modal-author modal-author"></h2> <img class="js-modal-preview modal-preview" src="" alt="" /> <button class="js-close-button close-button" data-close aria-label="Close modal" type="button"> <span aria-hidden="true">×</span> </button> </div><!-- .end Gallery modal --> </div><!-- .end Gallery overlay -->
Putting it all together
This is all we need for html to get this responsive gallery work. Well, almost. We will need to add link to include scripts that will enhance this responsive gallery with reveal dialog. That will be all. So, let’s now finish this part by putting together these three parts. Then, we can move on to Sass (or CSS) and add some styling to our responsive gallery.
Whole HTML:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Responsive Gallery with Foundation</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.2.4/foundation-flex.min.css"> <link rel="stylesheet" href="styles/main.css"> </head> <body> <!-- Gallery wrapper --> <div class="gallery-wrapper row expanded"> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/zZzKLzKP24o/600x600" alt="Photo by Caleb George" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/3YfSwCfJ6Do/600x600" alt="Photo by Garth Pratt" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/8Pd8yCjjKIQ/600x600" alt="Photo by Maxime Le Conte des Floris" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/2Bjq3A7rGn4/600x600" alt="Photo by Martin Jernberg" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/EDqP5r_QwrE/600x600" alt="Photo by Alec Weir" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/IEqPWQvnR1E/600x600" alt="Photo by Jaclyn Clark" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/4KgtxwMeLYw/600x600" alt="Photo by Andrew Collins" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/GnU2altkUSQ/600x600" alt="Photo by Clem Onojeghuo" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/Yfyt6q8gjaQ/600x600" alt="Photo by Clem Onojeghuo" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/8soQzdz9XXA/600x600" alt="Photo by Clem Onojeghuo" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/myFsTTkub9E/600x600" alt="Photo by Scott Webb" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/3kmDKoHY7as/600x600" alt="Photo by Matheus Ferrero" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/ZMRMFULofus/600x600" alt="Photo by Joel Filipe" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/n3FM6tfn9XQ/600x600" alt="Photo by Aaron Barnaby" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/SdEDmcrJOE4/600x600" alt="Photo by Geetanjal Khanna" /> </a> </div> <div class="medium-6 large-3 xlarge-2"> <a href="#" data-toggle="galleryModal"> <img src="https://source.unsplash.com/6hC831t-ihM/600x600" alt="Photo by Anton Romanov" /> </a> </div> </div><!-- .end Gallery wrapper --> <!-- Gallery overlay --> <div class="js-gallery-overlay gallery-overlay reveal-overlay"> <!-- Gallery modal --> <div class="js-gallery-reveal gallery-reveal reveal" id="galleryModal" data-reveal data-overlay="true"> <h2 class="js-modal-author modal-author"></h2> <img class="js-modal-preview modal-preview" src="" alt="" /> <button class="js-close-button close-button" data-close aria-label="Close modal" type="button"> <span aria-hidden="true">×</span> </button> </div><!-- .end Gallery modal --> </div><!-- .end Gallery overlay --> <!-- Scripts --> <script src="scripts/main.js"></script> </body> </html>
CSS and Sass
The biggest benefit of using a front-end framework, such as Foundation, is that you don’t have to style everything. In case of this responsive gallery, Foundation will take care about the majority of styling. However, we will hack it and add couple of overrides. Before we add these overrides, let’s also add one Sass variable and function to make our work easier. We will use that variable for breakpoint. This will be our first hack. What about that function? It will convert pixels to rems.
Sass:
// Function to convert px to rems @function remy($value, $base: 16px) { @return ($value / $base) * 1rem; } // Variables $breakpoint-xlarge: 1200px;
This is all for our Sass workflow. What if you are not familiar with Sass and you want to learn it? Then, check out this short 5-minute Sass tutorial I prepared for you. Our next step will be resetting the font-size of html and body elements. We will be using rem units and this will help us keep styles consistent. Quick side note: Foundation sets font-size of html to “100%”. And, what about body element? It leaves it untouched.
Sass:
/* Base resets */ html { font-size: 16px; } body { font-size: 100%; }
Hacking the grid and adding new columns
Now, it is time to introduce our first hacks. We will create additional column for grid. This column will use class xlarge-* and will target resolution 1200px and higher ($breakpoint-xlarge variable). This means that we will have to create styles for all twelve columns for this breakpoint. Well, we can create just one column. This responsive gallery will use only xlarge-2 class. Therefore, we can create styles only for this class. However, I decided to create styles for all twelve columns in case you want to use different grid structure.
Sass:
/* Extending Foundation grid */ @media screen and (min-width: $breakpoint-xlarge) { .xlarge-1 { flex: 0 0 8.33333%; max-width: 8.33333% } .xlarge-2 { flex: 0 0 16.66667%; max-width: 16.66667% } .xlarge-3 { flex: 0 0 25%; max-width: 25% } .xlarge-4 { flex: 0 0 33.33333%; max-width: 33.33333% } .xlarge-5 { flex: 0 0 41.66667%; max-width: 41.66667% } .xlarge-6 { flex: 0 0 50%; max-width: 50% } .xlarge-7 { flex: 0 0 58.33333%; max-width: 58.33333% } .xlarge-8 { flex: 0 0 66.66667%; max-width: 66.66667% } .xlarge-9 { flex: 0 0 75%; max-width: 75% } .xlarge-10 { flex: 0 0 83.33333%; max-width: 83.33333% } .xlarge-11 { flex: 0 0 91.66667%; max-width: 91.66667% } .xlarge-12 { flex: 0 0 100%; max-width: 100% } }
Hacking reveal overlay and dialog
Let’s move to the second, third and fourth hack. There are couple of things in Foundation I didn’t like. First, it shows vertical scrollbar in overlay. I think that it is necessary to do that unless the content doesn’t fit the overlay. Therefore, we will set the overflow property of reveal-overlay to “auto”. Next thing is that Foundation doesn’t vertically and horizontally center the reveal dialog. We will fix that by using a combo of position, top, left and transform properties.
Another thing that Foundation does is that it sets the min-height and height to “100vh” on small screens. This is not necessary. Also, it might look very bad if the image is also not full-height. So, we will reset this behavior by setting the min-height to “auto” and height to “1px”. The last two things related to reveal dialog are removing default border and adding very subtle box-shadow.
Sass:
/* Override for Foundation reveal overlay */ .reveal-overlay { overflow: auto; } /* Override for Foundation reveal (modal) */ .gallery-reveal { position: absolute; top: 50%; left: 50%; min-height: 1px; height: auto; border: 0; box-shadow: 0 remy(2px) remy(4px) rgba(0, 0, 0, .5); transform: translate(-50%, -50%); }
Let’s now take a quick look at the content of our reveal dialog. There are two things we need to take about. The first one is styling h2 heading we used to show the author of photo. You can also use it for a short info about the photo. Finally, let’s make the change of button color on hover a bit smoother by adding transition.
Sass:
/* Custom styles for author */ .modal-author { margin-bottom: remy(8px); font-size: remy(16px); } .close-button { transition: color .25s cubic-bezier(.4, 0, 1, 1); }
Putting it all together
This is everything we need for our responsive gallery in case of Sass. Again, let’s put all the styles we created above together.
Sass:
// Function to convert px to rems @function remy($value, $base: 16px) { @return ($value / $base) * 1rem; } // Variables $breakpoint-xlarge: 1200px; /* Base resets */ html { font-size: 16px; } body { font-size: 100%; } /* Extending Foundation grid */ @media screen and (min-width: $breakpoint-xlarge) { .xlarge-1 { flex: 0 0 8.33333%; max-width: 8.33333% } .xlarge-2 { flex: 0 0 16.66667%; max-width: 16.66667% } .xlarge-3 { flex: 0 0 25%; max-width: 25% } .xlarge-4 { flex: 0 0 33.33333%; max-width: 33.33333% } .xlarge-5 { flex: 0 0 41.66667%; max-width: 41.66667% } .xlarge-6 { flex: 0 0 50%; max-width: 50% } .xlarge-7 { flex: 0 0 58.33333%; max-width: 58.33333% } .xlarge-8 { flex: 0 0 66.66667%; max-width: 66.66667% } .xlarge-9 { flex: 0 0 75%; max-width: 75% } .xlarge-10 { flex: 0 0 83.33333%; max-width: 83.33333% } .xlarge-11 { flex: 0 0 91.66667%; max-width: 91.66667% } .xlarge-12 { flex: 0 0 100%; max-width: 100% } } /* Override for Foundation reveal overlay */ .reveal-overlay { overflow: auto; } /* Override for Foundation reveal (modal) */ .gallery-reveal { position: absolute; top: 50%; left: 50%; min-height: 1px; height: auto; border: 0; box-shadow: 0 remy(2px) remy(4px) rgba(0, 0, 0, .5); transform: translate(-50%, -50%); } /* Custom styles for author */ .modal-author { margin-bottom: remy(8px); font-size: remy(16px); } .close-button { transition: color .25s cubic-bezier(.4, 0, 1, 1); }
JavaScript
This is the third and last part of this responsive gallery tutorial. In this part, we will add a bit of JavaScript to handle the reveal overlay and dialog. Also, we will write some simple scripts for showing the clicked image in a preview inside the reveal dialog. The first step is getting the html elements we will work with and storing them inside variables. Let’s put all these variables inside one object literal. This will help us keep the code tidy. I used const because they will not change.
JavaScript (ES6):
(() => { const galleryVariables = { galleryAuthor: document.querySelector('.js-modal-author'), galleryButton: document.querySelector('.js-close-button'), galleryLinks: document.querySelectorAll('a[data-toggle="galleryModal"]'), galleryModal: document.querySelector('.js-gallery-reveal'), galleryOverlay: document.querySelector('.js-gallery-overlay'), galleryPreview: document.querySelector('.js-modal-preview'), galleryPreviewAuthor: document.querySelector('.js-modal-author') } })();
Adding custom fade in and fade out functions
If we want to show or hide the reveal, we can use a bit of JavaScript to change its CSS display property. However, this doesn’t look very good. We can make this interaction much smoother. So, let’s create two functions, fadeIn and fadeOut. These functions will use setInterval and CSS opacity and display property to show the reveal dialog.
JavaScript (ES6):
// Fade in function const fadeIn = (element) => { // Create variable with initial opacity let elementOpacity = 0.1; // Create timer for fadeIn function let timer = setInterval(() => { if (elementOpacity >= 1) { // Reset interval clearInterval(timer); } // Set element opacity to elementOpacity element.style.opacity = elementOpacity; // Increase value of elementOpacity elementOpacity += elementOpacity * 0.1; // Show element element.style.display = 'block'; }, 15); } // Fade out function const fadeOut = (element) => { // Create variable with initial opacity let elementOpacity = 1; // Create timer for fadeOut function let timer = setInterval(() => { if (elementOpacity <= 0.1) { // Reset interval clearInterval(timer); // Hide element element.style.display = 'none'; } // Set element opacity to elementOpacity element.style.opacity = elementOpacity; // Decrease value of elementOpacity elementOpacity -= elementOpacity * 0.1; }, 15); }
Showing reveal overlay and reveal dialog
Next, we will use for loop to loop through all the anchor tags with images. Then, we will use addEventListener to take extract the data in alt and src attributes and from clicked image. This is done by using getAttribute() method and textContent property. We will then take this data and use setAttribute() method to update the img element inside the reveal dialog. After that, we will check if all these information are in place. If it’s true, we will hide overflow of body element, set display property of reveal dialog to “block” and use fadeIn function to show the reveal overlay. As a result, we will smoothly reveal the reveal dialog with proper preview image.
JavaScript (ES6):
// Open reveal dialog by clicking on images for (let x = 0, y = galleryVariables.galleryLinks.length; x < y; x++) { // Add event listener for image containers galleryVariables.galleryLinks[x].addEventListener('click', (e) => { e.preventDefault(); // Get clicked image let image = e.target; // Get src of the image let imageSrc = image.getAttribute('src'); // Get alt of the image let imageAlt = image.getAttribute('alt'); // Set alt attribute of preview image to clicked image galleryVariables.galleryPreview.setAttribute('alt', imageAlt); // Set src attribute of preview image to clicked image galleryVariables.galleryPreview.setAttribute('src', imageSrc); // Set preview headline to alt of clicked photo galleryVariables.galleryPreviewAuthor.textContent = imageAlt; // Avoid openning modal unless its content is loaded if (galleryVariables.galleryPreview.getAttribute('src').length > 0 && galleryVariables.galleryPreview.getAttribute('alt').length > 0 && galleryVariables.galleryPreviewAuthor.textContent.length > 0) { // Add Foundation class to hide overflow document.body.classList.add('is-reveal-open'); // Show modal dialog galleryVariables.galleryModal.style.display = 'block'; // Show modal overlay (fade it in) fadeIn(galleryVariables.galleryOverlay); } }); }
Closing reveal overlay and reveal dialog
Okay, we have a way to open the reveal dialog. The last thing we need is some function to close it. Let’s create new event listener and bind it to the close button inside the reveal dialog. To do this, we will first use our fadeOut function and wait for a moment. Otherwise, the effect of closing reveal dialog wouldn’t be as smooth as we want. So, let’s use setTimeout method and use display property to hide the reveal dialog. In addition, we will use setAttribute() method and textContent property to reset the preview image and info text. Finally, we will rest overflow of body element.
JavaScript (ES6):
// Close reveal dialog galleryVariables.galleryButton.addEventListener('click', (e) => { e.preventDefault(); // Hide modal overlay (fade it out) fadeOut(galleryVariables.galleryOverlay); // Wait before overlay fades out setTimeout(() => { // Hide modal dialog galleryVariables.galleryModal.style.display = 'none'; // Reset alt attribute of preview image galleryVariables.galleryPreview.setAttribute('alt', ''); // Reset src attribute of preview image galleryVariables.galleryPreview.setAttribute('src', ''); // Reset text for preview headline galleryVariables.galleryPreviewAuthor.textContent = ''; // Remove Foundation class to hide overflow document.body.classList.remove('is-reveal-open'); }, 250); });
Putting it all together
This is the JavaScript code we need to make this responsive gallery work. Now, let’s put all the previous JavaScript parts together. Then, you will see the whole code for our responsive gallery at once.
JavaScript (ES6):
(() => { 'use strict'; // Create object literal with project variables const galleryVariables = { galleryAuthor: document.querySelector('.js-modal-author'), galleryButton: document.querySelector('.js-close-button'), galleryLinks: document.querySelectorAll('a[data-toggle="galleryModal"]'), galleryModal: document.querySelector('.js-gallery-reveal'), galleryOverlay: document.querySelector('.js-gallery-overlay'), galleryPreview: document.querySelector('.js-modal-preview'), galleryPreviewAuthor: document.querySelector('.js-modal-author') } // Fade in function const fadeIn = (element) => { // Create variable with initial opacity let elementOpacity = 0.1; // Create timer for fadeIn function let timer = setInterval(() => { if (elementOpacity >= 1) { // Reset interval clearInterval(timer); } // Set element opacity to elementOpacity element.style.opacity = elementOpacity; // Increase value of elementOpacity elementOpacity += elementOpacity * 0.1; // Show element element.style.display = 'block'; }, 15); } // Fade out function const fadeOut = (element) => { // Create variable with initial opacity let elementOpacity = 1; // Create timer for fadeOut function let timer = setInterval(() => { if (elementOpacity <= 0.1) { // Reset interval clearInterval(timer); // Hide element element.style.display = 'none'; } // Set element opacity to elementOpacity element.style.opacity = elementOpacity; // Decrease value of elementOpacity elementOpacity -= elementOpacity * 0.1; }, 15); } // Open reveal dialog by clicking on images for (let x = 0, y = galleryVariables.galleryLinks.length; x < y; x++) { // Add event listener for image containers galleryVariables.galleryLinks[x].addEventListener('click', (e) => { e.preventDefault(); // Get clicked image let image = e.target; // Get src of the image let imageSrc = image.getAttribute('src'); // Get alt of the image let imageAlt = image.getAttribute('alt'); // Set alt attribute of preview image to clicked image galleryVariables.galleryPreview.setAttribute('alt', imageAlt); // Set src attribute of preview image to clicked image galleryVariables.galleryPreview.setAttribute('src', imageSrc); // Set preview headline to alt of clicked photo galleryVariables.galleryPreviewAuthor.textContent = imageAlt; // Avoid openning modal unless its content is loaded if (galleryVariables.galleryPreview.getAttribute('src').length > 0 && galleryVariables.galleryPreview.getAttribute('alt').length > 0 && galleryVariables.galleryPreviewAuthor.textContent.length > 0) { // Add Foundation class to hide overflow document.body.classList.add('is-reveal-open'); // Show modal dialog galleryVariables.galleryModal.style.display = 'block'; // Show modal overlay (fade it in) fadeIn(galleryVariables.galleryOverlay); } }); } // Close reveal dialog galleryVariables.galleryButton.addEventListener('click', (e) => { e.preventDefault(); // Hide modal overlay (fade it out) fadeOut(galleryVariables.galleryOverlay); // Wait before overlay fades out setTimeout(() => { // Hide modal dialog galleryVariables.galleryModal.style.display = 'none'; // Reset alt attribute of preview image galleryVariables.galleryPreview.setAttribute('alt', ''); // Reset src attribute of preview image galleryVariables.galleryPreview.setAttribute('src', ''); // Reset text for preview headline galleryVariables.galleryPreviewAuthor.textContent = ''; // Remove Foundation class to hide overflow document.body.classList.remove('is-reveal-open'); }, 250); }); });
Closing thoughts on building responsive gallery with Foundation
Hey, congrats! You’ve just finished this tutorial and created responsive gallery with custom reveal dialog. Chances are that you’ve also learned a bit about Foundation framework and ES6. So, now you can take what you’ve learned and implement it. And, what if you want to take this responsive gallery on another level? You can take a look at this React tutorial and follow this tutorial using React! Have a great day and see you soon.
If you liked this article, please subscribe so you don't miss any future post.
If you'd like to support me and this blog, you can become a patron, or you can buy me a coffee 🙂