Unlimited Wordpress themes, plugins, graphics & courses! Unlimited asset downloads! From \$16.50/m

# How to Build a Draggable Image Gallery and a Custom Lightbox With GSAP

In a previous tutorial, we learned how to build a responsive image gallery with slick.js. Today, let’s build something similar yet even more complete: a responsive image gallery with a draggable featured image/main slide and a responsive lightbox gallery that sits on top of it. To make the target element draggable, we’ll take advantage of GSAP’s Draggable plugin.

Sounds like a good exercise?

## What We’re Building

Here’s the component that we’re going to create:

Be sure to open the lightbox gallery by clicking on the Open Lightbox button.

## 1. Include the Required Plugins

As already discussed, to make the featured images draggable elements, we’re going to use GSAP and specifically its Draggable plugin.

You can achieve this functionality by using another plugin or even with pure JavaScript events

Optionally, we’ll also include InertiaPlugin (formerly ThrowPropsPlugin), a second GSAP plugin that will apply a momentum-based movement after the mouse/touch is released. It’s worth noting that this is a premium plugin, and you have to sign up for a GSAP membership before deciding to use it. In our case, we’re going to use a trial version that only works locally and on domains like codepen.io (see the browser console of the demo for more details).

With all these in mind, we’ll include three external JavaScript files. The first two are mandatory, while the third one is optional.

## 2. Define the HTML Markup

### Set the Markup for the Gallery

We’ll first define a wrapper element that will contain:

• The lists of thumbnail and featured images. Both lists will include the same Unsplash images. These will have equal dimensions and be big enough to implement the draggable effect.
• The button for opening the lightbox gallery.

By default, the first main slide will appear. But we can configure that behavior by attaching the is-active class to the desired slide (lists).

In addition, all featured images will retain their original dimensions (1920px x 1280px).

Here’s the required structure for our gallery:

### Set the Markup for the Lightbox Gallery

Next, we'll define a lightbox component that will include:

• A list with the aforementioned Unsplash images. Depending on the active main slide, the related lightbox image will appear.
• The navigation arrows for switching between slides.
• A close button

Here’s the required structure for our lightbox:

## 3. Specify the Main Styles

With the markup ready, we’ll continue with the main styles of our page. For simplicity, I’ll skip the introductory/reset ones. Also, I won’t optimize or merge the common CSS styles, so it will be easier for you to understand what is going on. Be sure to see all of them by clicking the CSS tab of the demo.

### Set Gallery Layout

The gallery will have a maximum width of 950px.

On large screens (>750px), we’ll have two columns. The thumbnails will appear on the left side, while the featured images will be on the right, like this:

Notice that the thumbnails will cover a quarter of the gallery width, while the featured images will cover three-quarters.

On small screens (≤750px), the thumbnails will sit underneath the featured image, like this:

Notice that each thumbnail will cover one-quarter of the parent’s width.

Here are the associated styles:

### Featured Slides Visibility

By default, all featured slides will be hidden, apart from the active slide. Plus, only one featured slide (the active one) will appear at a time.

Here are the associated styles:

### Position Featured Images

On large screens, both gallery columns will have the same height as they are grid items. The featured images though will be absolutely positioned elements and centered within their container. To view all their parts we have to drag over them.

On small screens, as the columns are stacked and the featured images are still absolutely positioned, we should specify a fixed height for the right column.

Here are the associated styles:

### Indicate Active and Hovered States

Each time we hover over a thumbnail, its ::before pseudo-element will appear. This will have a light blue background and sit on top of the thumbnail.

On the other hand, the active thumbnail will receive a red border color.

Here are the associated styles:

### Set Lightbox Styles

By default, the lightbox will be hidden and appear only when someone clicks on the corresponding call-to-action button.

Here are some things to note about the lightbox styles:

• The lightbox will be a fixed positioned element with horizontally centered content.
• The navigation and close buttons will be absolutely positioned elements.
• The gallery will be vertically centered and only one of its images will appear at a time. This will depend on the active featured slide.
• The images will have a maximum height equal to the viewport height and their width will be set to auto

Here's a part of these styles:

Let’s now give life to our component!

Again, for simplicity, I won’t optimize/merge the JavaScript code. Feel free to grab the code parts that work for your projects.

### Change Gallery Slides

Each time we click on a thumbnail, we’ll perform the following actions:

• Remove the is-active class from the pre-existing active thumbnail and featured image.
• Find the index of the current active thumbnail.
• Assign the is-active class to the active thumbnail and the featured image whose index matches the index of this thumbnail.

Here’s the required code:

Going even further, we'll enhance the previous functionality by providing support for keyboard navigation. More specifically:

• Each time the up () or down () arrow keys are pressed, we’ll retrieve the pre-existing active thumbnail.
• If the up arrow key is pressed, the thumbnail that precedes the current thumbnail will become active. In case there isn’t any such thumbnail, the last thumbnail will become active.
• If the down arrow key is pressed, the thumbnail that follows the current thumbnail will become active. In case there isn’t any such thumbnail, the first thumbnail will become active.

Here’s the required code:

As an enhancement, you can switch the up/down arrows for the left/right ones on the mobile layout

### Make Feature Images Draggable

Coming up next, we’ll make the featured images draggable elements. As already discussed earlier, to do this, we’ll take advantage of GSAP's Draggable plugin. We'll instantiate the plugin through its create() method and pass it the two following arguments:

• The elements that we want to drag.
• A configuration object. Inside it, we’ll specify the bounds at which the draggable elements should stay during the effect. Optionally, as we’ve loaded the InertiaPlugin, we’ll also request through the inertia property momentum-based motion after users’ mouse/touch is released.

Here’s the corresponding code:

Of course, here, we covered just the basic part of the plugin’s functionality. You can go even deeper by reading the docs and implementing complex stuff.

### Open Lightbox

As already pointed, the lightbox will appear as soon as we click on the Open Lightbox button. So upon click, we’ll perform the following actions:

• Remove the is-active class from the pre-existing active lightbox image, if there's any.
• Remove the vertical scrollbar from the body element through the overflow-y-hidden class.
• Find the index of the current active featured image.
• Assign the is-active class to the lightbox image whose index matches the index of this featured image.
• Reveal the lightbox through the is-visible class.

Here’s the required code:

### Close Lightbox

There are two different ways for closing the lightbox:

• Firstly, by clicking on the .close-lightbox element that sits inside the lightbox header.
• Secondly, by pressing the Esc key.
Once again, here's the required code:

### Change Lightbox Slides

Each time we click on a navigation arrow, we’ll perform the following actions:

• Grab a copy of the currently active lightbox slide.
• Remove the is-active class from this slide.
• Check to see which button is clicked. If that’s the next one, we’ll add the is-active class to the slide that follows the active one. If there isn’t such a slide, the first one will receive this class.
• On the other hand, if that's the previous one, we’ll add the is-active class to the slide that precedes the active one. If there isn’t such a slide, the last one will receive this class.

Here's the required code:

Like we did with the image gallery, let's make our lightbox more robust by adding support for keyboard navigation. More specifically:

• If the lightbox is visible, we check to see if the left () or right () arrow keys are pressed.
• If the left arrow key is pressed, we'll force a click to the previous navigation control.
• In the same way, if the right arrow key is pressed, we'll force a click to the next navigation control.

Here’s the required code:

## Conclusion

Another exercise has come to an end, folks! Thanks for following along. Hopefully, you enjoyed what we built today, and it gave you a solid knowledge of how to combine some custom code with the power of popular plugins like GSAP.

Here’s a reminder of what we built:

Last but not least, remember that GSAP isn’t the only way to create a draggable effect. You’re more than welcome to try another option and share it with us. Also, if you want to effortlessly add swipe support on the lightbox, you might want to try a JavaScript library like Hammer.js.

As always, thanks a lot for reading!