Slick Carousel Responsive slidesToShow Recipe

Designs typically require more than the out of the box demos provide, which is understandable. The slick carousel demos will get you most of the way there and provide examples for various settings. This post is an example of how to dynamically update the slick slidesToShow value as the viewport is resized, demo.

Getting Started

In this tutorial, we’re using the Parcel web application bundler to compile all of source code and load it in a development web server. All of our markup, JavaScript and CSS will be created in a subdirectory named src, short for source. In the project root, create the src folder. Then, create an html file in the src folder with the following HTML. This markup contains 4 slide content containers for the carousel. The content container include FPO images and a heading.

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Responsive slidesToShow | Slick Carousel Demo</title>
    <link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
    <main>
        <div class="carousel">
            <div>
                <div class="slide-content">
                    <h3>First Slide</h3>
                    <img src="https://via.placeholder.com/260x200/9932CC/FFFFFF" />
                </div>
            </div>
            <div>
                <div class="slide-content">
                    <h3>Second Slide</h3>
                    <img src="https://via.placeholder.com/260x200/7FFFD4/000000" />
                </div>
            </div>
            <div>
                <div class="slide-content">
                    <h3>Third Slide</h3>
                    <img src="https://via.placeholder.com/260x200/87CEFA/000000" />
                </div>
            </div>
            <div>
                <div class="slide-content">
                    <h3>Fourth Slide</h3>
                    <img src="https://via.placeholder.com/260x200/F4A460/000000" />
                </div>
            </div>
        </div>
    </main>
    <script src="index.js"></script>
</body>
</html>

Using Emmet, which is built into VS Code, you can create the index.html content by entering an exclamation mark on the first line then select the tab key.

Since we’re using npm to install the slick carousel and it’s dependencies, in the project root, run npm init with the -y flag to generate an empty project with the default settings.

npm init -y

Install slick carousel.

npm install slick-carousel

Slick carousel depends on jQuery, so let’s install it.

npm install jquery

Create a src/index.css file in the project as follows. Note that we’re importing the slick stylesheets from slick in the node_modules folder where it was installed by npm. When we run our build later on, these imported stylesheets will be compiled along with the index.css below into a single stylesheet to reduce http requests made by the web application.

index.css
/* node_modules */
@import "../../node_modules/slick-carousel/slick/slick.css";
@import "../../node_modules/slick-carousel/slick/slick-theme.css";

body {
  margin: 0;
}

main {
  max-width: 1440px;
  margin: auto;
  padding: 10px;
  background: #cfcfcf;
}

.carousel {
  margin-right: -10px;
}

.slide-content {
  display: inline-block;
  background: #fff;
  padding: 15px;
  text-align: center;
}

@media screen and (min-width: 980px) {
  main {
    padding: 50px;
  }

  .carousel {
    max-width: 980px;
    margin: auto;
  }
}

Here is our JavaScript code. Add this to a src/index.js file.

index.js
import $ from 'jquery'
import 'slick-carousel'

(function () {

  var slidesToShow = 1.1,
      slideWidth = 290,
      slideSpacing = 30;

  var $el = $('.carousel');

  init();

  function init() {
    $el.on('init', (event, slick, currentSlide) => carouselInit(event, slick));

    $el.slick({
      arrows: false,
      dots: true,
      infinite: false,
      slidesToScroll: 1,
      slidesToShow: slidesToShow,
      mobileFirst: true,
      responsive: [{
        breakpoint: 980,
        settings: {
          arrows: true,
          slidesToShow: 3
        }
      }]
    });

    $el.css('padding-left', slideSpacing / 2 + 'px');

    var resizeTimeout;
    $(window).on('resize', () => {
      clearTimeout(resizeTimeout);
      resizeTimeout = setTimeout(setSlidesToShow(), 500);
    })
  };

  function carouselInit(event, slick) {
    // https://github.com/kenwheeler/slick/issues/1802
    setTimeout(() => setSlidesToShow(), 0);
  };

  function setSlidesToShow() {
    if ($(window).width() >= 980) {
      return;
    }

    var num1, num2,
        slickListWidth = $el.find('.slick-list').width(),

    num1 = slickListWidth / slideWidth;
    num2 = Math.floor(num1) * slideSpacing;
    num1 = (slickListWidth - num2) / slideWidth;
    num1 = Math.floor(num1 * 100) / 100;

    console.log('slickListWidth', slickListWidth);
    console.log('slideWidth', slideWidth);
    console.log('slidesToShow', num1);

    $el.slick('slickSetOption', 'slidesToShow', num1);

    // refresh to apply slick-slide classes, dots etc. as needed
    $el.slick('resize');

    slidesToShow = num1;
  };

})();

In the JavaScript, we’re importing the slick library and jquery. Then we’re wrapping everything else in an IIFE (Immediately Invoked Function Expression).

Then we’re declaring some slide defaults for the slidesToShow calculation that will run when slick is initialized and again when the browser window is resized. e.g.,

var slidesToShow = 1.1,
    slideWidth = 290,
    slideSpacing = 30;

The $el variable is set with a jQuery selector for the HTML element slick carousel will bind to. e.g.,

var $el = $('.carousel');

The slick responsive option has a breakpoint setting of 980 with a constant slidesToShow setting that can be used when the browser window is at or greater than this width. In order for this responsive setting to remain constant, the 980 width value is checked in the setSlidesToShow function before it continues. e.g.,

if ($(window).width() >= 980) {
  return;
}

Now we’re ready to build the web app. Install Parcel to do this. e.g.,

npm install parcel-bundler -D

If you’re planning on using Parcel to bundle other projects, you might want to install it as a global module instead using npm install -g parcel-bundler.

npm-run-script

These npm script commands in the package.json file are what we will use to run the parcel commands.

The first script command to add, we’ll name dev:slidestoshow. This launches the parcel dev server, watches for file changes and rebuilds as needed.

The second script command to add, is named build:slidestoshow. This minifies the files for production. Note the --public-url option, this sets the asset paths as relative during the build.

package.json
"scripts": {
  "dev:slidestoshow": "parcel ./src/slides-to-show/slides-to-show.html",
  "build:slidestoshow": "parcel build ./src/slides-to-show/slides-to-show.html --public-url ./",
  "test": "echo \"Error: no test specified\" && exit 1"
},

One more thing to install is parcel-plugin-clean-dist. This will remove all the previous files when rebuilding for production.

Running the commands

Development

npm run dev:slidestoshow

If all went as expected, the terminal output will include a URL to the development server. e.g., Server running at http://localhost:1234.

Any code changes you make while running in this mode will be rebuilt and rendered on the server.

Production

npm run build:slidestoshow

Download the Code

All of the source code for this tutorial is available on GitHub as part of my uiCookbook repo.

Source Code

Part 2 of 2 in the Slick Carousel series.

Slick Lazy Load Photo Grid Using Webpack 3

comments powered by Disqus