# How to Build an Attractive Responsive Image Gallery With slick.js

In this tutorial we’ll use slick.js, a popular jQuery plugin, to build an attractive responsive image gallery. Here’s the gallery that we’re going to create:

Be sure to check the full screen version and resize your browser window to see how its layout changes depending on viewport size.

## What is slick.js?

Slick.js is a well-known jQuery plugin created by Ken Wheeler that lets you build beautiful responsive carousels. To better understand what this plugin can offer you, check out the documentation.

Happily, it works not only in all modern browsers, but also in some older ones like IE 8+.

Lastly, you might want to have a look at the WordPress version.

## Getting Started With slick.js

• jQuery (≥1.7)
• slick.css or its minified version
• slick.js or its minified version

Optionally, you might want to import the slick-theme.css file.

You can grab a copy of the corresponding slick files by visiting its Github repo, by using a package manager (e.g. npm), or by loading the necessary assets through a CDN (e.g. cdnjs). For this tutorial, I’ll choose the last option.

Additionally, I’ve incorporated Babel for compiling the ES6 code down to ES5 and Lodash for taking advantage of its debounce function (we’ll use that later).

With that in mind, if you look under the Settings tab of our demo pen, you’ll see that I’ve included one external CSS file and three external JavaScript files.

## 1. The HTML

At this point it’s important to understand the structure of our page. Most importantly, we’ll define two carousels which have the exact same images and are synchronized (we’ll discuss how later). The image dimensions are 860 x 550 pixels, though in your own projects, these might be different.

Lastly, as part of the second carousel we’ll specify the navigation arrows as well as an element which keeps track of the total number of slides.

Here’s the required structure for our demo page:

 1
2
3
4 5
6 12
13 14
15
16
17 18
19 20
21 29
30 31
32
33 34
35

## 2. The CSS

In total, our gallery should have four different appearances, depending on the viewport available. Let’s visualize them by following a mobile-first approach.

When the browser window is less than 480px, it should look like this, with only the second carousel and navigation appearing:

Then, on screens between 480px and 768px, it should be as follows, with two thumbnails under the main slide:

Next, on screens between 769px and 1023px, we’ll introduce a third thumbnail:

Finally, on large screens (≥1024px), it should be as follows, with the thumbnails appearing to the side (note that they don’t quite fit on this image in their entirety):

All the cases above are catered for in the media queries shown below:

 1 .synch-carousels { 2 position: relative; 3 display: flex; 4 flex-wrap: wrap; 5 justify-content: space-between; 6 } 7 8 .synch-carousels > * { 9 width: 100%; 10 } 11 12 .synch-carousels .right { 13 order: -1; 14 } 15 16 .synch-carousels .left { 17 overflow: hidden; 18 } 19 20 .synch-carousels .gallery { 21 display: none; 22 } 23 24 .synch-carousels .gallery .slick-list { 25 height: auto !important; 26 margin: 0 -20px; 27 } 28 29 .synch-carousels .gallery .slick-slide { 30 margin: 0 20px; 31 } 32 33 @media screen and (min-width: 480px) { 34 .synch-carousels .right { 35 margin-bottom: 20px; 36 } 37 38 .synch-carousels .gallery { 39 display: block; 40 } 41 } 42 43 @media screen and (min-width: 1024px) { 44 .synch-carousels .right { 45 position: relative; 46 width: calc(100% - 230px); 47 margin-bottom: 0; 48 order: 2; 49 } 50 51 .synch-carousels .left { 52 width: 210px; 53 } 54 55 .synch-carousels .gallery .slick-slide { 56 margin: 0 0 20px 0; 57 } 58 59 .synch-carousels .gallery .slick-list { 60 margin: 0; 61 } 62 }

Notice there’s an !important rule. This overwrites an inline slick style.

## 3. The JavaScript

Let’s now turn our attention to the JavaScript-related things.

### Caching Selectors

When the DOM is ready, as a good practice we cache some commonly-used selectors:

 1 const $left =$(".left"); 2 const $gl =$(".gallery"); 3 const $gl2 =$(".gallery2"); 4 const $photosCounterFirstSpan =$(".photos-counter span:nth-child(1)");

### Initializing the Carousels

Then, we initialize and synchronize our two carousels. The code responsible for this behavior is as follows:

 1 $gl.slick({ 2 rows: 0, 3 slidesToShow: 2, 4 arrows: false, 5 draggable: false, 6 useTransform: false, 7 mobileFirst: true, 8 responsive: [ 9 { 10 breakpoint: 768, 11 settings: { 12 slidesToShow: 3 13 } 14 }, 15 { 16 breakpoint: 1023, 17 settings: { 18 slidesToShow: 1, 19 vertical: true 20 } 21 } 22 ] 23 }); 24 25$gl2.slick({ 26 rows: 0, 27 useTransform: false, 28 prevArrow: ".arrow-left", 29 nextArrow: ".arrow-right", 30 fade: true, 31 asNavFor: $gl 32 }); Without doubt, the best way to understand how this code works is to read the slick documentation. However, let me explain two important things here: • The asNavFor configuration option allows us to synchronize the carousels and use one as the navigation for the other. • By default, slick uses CSS transforms. In our case though, we disable them by setting useTransform: false. This is because they cause a small flickering in the first slide of the first carousel on large screens (we could have disabled them only for the first carousel). ### Displaying and Customizing the Gallery Layout Our gallery should be visible only when all page assets are ready. Initially, an optional preloader appears–refer to the markup again, it looks like this:  1 Carousel is loading... At this point, we have to think again about the desired gallery layout on large screens. If you look back at the corresponding screenshots, you’ll notice that both carousels have the same heights. In order to achieve that desired behavior, we have to write some custom JavaScript code (beyond our CSS). This code will dynamically set the height of the first carousel equal to the height of the second one (or vice versa). Knowing the requirements above, here’s the code that runs when the entire page is ready:  1$(window).on("load", () => { 2 handleCarouselsHeight(); 3 setTimeout(() => { 4 $(".loading").fadeOut(); 5$("body").addClass("over-visible"); 6 }, 300); 7 });

And here’s the declaration of the handleCarouselsHeight function:

 1 function handleCarouselsHeight() { 2 if (window.matchMedia("(min-width: 1024px)").matches) { 3 const gl2H = $(".gallery2)").height(); 4$left.css("height", gl2H); 5 } else { 6 $left.css("height", "auto"); 7 } 8 } When the page loads, the gallery works fine. But it should also work as expected when the browser window gets resized. The code that deals with that particular situation is shown below:  1$(window).on( 2 "resize", 3 _.debounce(() => { 4 handleCarouselsHeight(); 5 }, 200) 6 );

Notice that the event handler is wrapped inside a debounce function. This a Lodash function that helps us restrict the amount of times this handler is called.

### Working With slick Events and Methods

Now that we've successfully implemented the main functionality of our gallery, let’s go a step further and build a few optional things.

First, at the top right corner of the second carousel we display the current slide and the total number of slides.

To accomplish this, we take advantage of the init and afterChange slick events.

Here’s the related code:

 1 /*you have to bind init event before slick's initialization (see demo) */ 2 gl2.on("init", (event, slick) => { 3 $photosCounterFirstSpan.text(${slick.currentSlide + 1}/); 4 $(".photos-counter span:nth-child(2)").text(slick.slideCount); 5 }); 6 7$gl2.on("afterChange", (event, slick, currentSlide) => { 8 $photosCounterFirstSpan.text(${slick.currentSlide + 1}/); 9 });

As a further improvement, each time we click on a slide of the first carousel, the associated slide of the second carousel should be active. Thanks to slick’s slickGoTo method, we’re able to develop this functionality.

Here’s the related code:

 1 $(".gallery .item").on("click", function() { 2 const index =$(this).attr("data-slick-index"); 3 \$gl2.slick("slickGoTo", index); 4 });

## 4. Browser Support

The demo should work well in all recent browsers and you can safely use it in your projects.

I’ve only encountered one small bug in some browsers (Firefox, Edge) while testing the demo on large screens. As you click on the navigation arrows, all slides of the first carousel apart from the first one, fail to reach the top edge of their parent and leave a single pixel gap:

Last but not least, small improvements and customizations might be needed as the window gets resized, depending on your needs.

## Conclusion

In this tutorial, we took advantage of slick.js and managed to build a beautiful responsive gallery. Hopefully now, you’re ready to try this implementation in your own projects. If that happens, feel free to share your project link in the comments below!