Better Than Bootstrap Javascript: Carousels

Carousel

This entry is part 2 of 3 in the series Better Than Bootstrap Javascript

Last week we started small, and looked to improve the perceived performance of our website with interactive loaders. We looked at what Bootstrap had to offer out of the box, and then explored a more robust option with the Ladda plugin.

This week we’re aiming to improve the carousel experience. Carousels are ubiquitous on the web and are used for a wide variety of purposes – from picture slideshows to client testimonials to an entire web page experience. And while there are some people who say you shouldn’t be using carousels, the bottom line is they won’t be going away soon, and are a useful tool to use and understand.

So let’s start by taking a look at the Bootstrap approach.

Bootstrapping our Carousel

In comparison to Bootstrap loaders and buttons, Carousels is a more meaty area of functionality.

Here’s an example of a simple Bootstrap Carousel.

<div class="carousel slide" data-ride="carousel">
  <ol class="carousel-indicators">
    <li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
    <li data-target="#carousel-example-generic" data-slide-to="1"></li>
    <li data-target="#carousel-example-generic" data-slide-to="2"></li>
  </ol>
  <div class="carousel-inner" role="listbox">
    <div class="item active">
      <img src="slide-1.jpg" alt="First slide">
    </div>
    <div class="item">
      <img src="slide-2.jpg" alt="Second slide">
    </div>
    <div class="item">
      <img src="slide-3.jpg" alt="Third slide">
    </div>
  </div>
  <a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
    <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
    <span class="sr-only">Previous</span>
  </a>
  <a class="right carousel-control" href="#carousel-exa mple-generic" role="button" data-slide="next">
    <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
    <span class="sr-only">Next</span>
  </a>
</div>

To setup the Bootstrap Carousel, you need to manually specify all of the html elements that go into it.

The .carousel class specifies the carousel container.

The .slide class specifies how to transition – in this case sliding. The alternative is to remove the class and the images change immediately.

The .carousel-indicators list specifies the position indicators at the bottom of the carousel.

.carousel-inner is the main content of the carousel, and the elements that get displayed are labeled with an .item class. To make sure your carousel displays at all, you have to make sure one of the items has an .active class applied to it.

For moving back and forward in the carousel, we have the .carousel-control class, and the data attribute data-slide with a value of “prev” or “next”.

Having specified all your markup, you can initialize the carousel in one of two ways.

1. Apply the data attribute data-ride="carousel". The plugin automatically applies carousel functionality to any markup on the page with that data attribute, on page load.

<div class="carousel slide" data-ride="carousel">

2. Initialize the carousel manually in Javascript

$('.carousel').carousel();

The result for our efforts is a carousel with clickable position indicators, click forward and back navigation, and that gives a baseline level of responsiveness based on screen size (it becomes smaller or larger as the screen size changes). It works the way we expect and gives us a solid carousel experience.

See the Pen Bootstrap Carousel by JP Camara (@jpcamara) on CodePen.

In addition to what i’ve shown, the plugin also offers a couple events (before and after the carousel slide has occurred), a few configuration options, and an API for manually pausing and moving forward and backward in the slides.

You can see that the functionality is limited, and the setup is very manual. We specify every piece of our html, and the capabilities we have beyond what you saw in the example are limited. What if we want additional transitions? What other capabilities are there for responsiveness? How fluid is the interaction on mobile?

Truthfully, I’ve never decided to go with the Bootstrap Carousel on any of my projects. The alternatives are just too good, and equally as easy (or easier) to setup. I’d suggest always using one of the alternatives, unless you have a real restriction on a project and can’t bring in outside libraries.

Flexslider

“Best responsive slider. Period.”

The first alternative to Bootstrap i’m presenting is Flexslider. Their boastful claim aside, it is a great carousel library and the functionality it delivers is pretty compelling.

Flexslider is a robust solution and was my go-to for a long time. It offers tons of flexibility, works great on mobile, has integrated swiping and comes with more levels of responsiveness.

Let’s look at an example of our markup.

<div id="flexslider-carousel" class="flexslider">
  <ul class="slides">
    <li>
      <img src="slide-1.jpg" />
    </li>
    <li>
      <img src="slide-2.jpg" />
    </li>
    <li>
      <img src="slide-3.jpg" />
    </li>
  </ul>
</div>

The thing we immediately notice is the simplicity of what we need to setup. Whether this is a good thing or not is a matter of preference. The Bootstrap markup is very manually specified, but that gives a decent level of control over exactly what is presented. With Flexslider, it does most of the setup for you and you just specify a small set of markup for it to enhance. It’s something of a Convention over Configuration approach – we provide Flexslider with a simple, consistent structure and it will handle the rest for us. Control over the output past that point comes in the form of configuration options and CSS styling. Personally, I prefer the slimmed down setup so I’m a fan of the Flexslider approach.

The conventional Flexslider setup contains the following pieces.

An outer container with a class of .flexslider.

An inner list of elements, with a class of .slides. This contains typical li items. Whatever content they contain is the content of the carousel.

And that’s it. A couple classes and a list. Having specified that markup, you can initialize the plugin by using the Flexslider API. We’ll also pass in a configuration option of animation here, to achieve the same transition that our Bootstrap example had.

$('.flexslider').flexslider({
  animation: 'slide'
});

The results of that effort in this case result in an experience similar to what the Bootstrap plugin offered. It has position indicators, forward and back navigation, and responds to screen size.

See the Pen Flexslider Carousel by JP Camara (@jpcamara) on CodePen.

So if we’re getting a very similar experience, is the only benefit we get is that there’s less markup? Isn’t that just a matter of preference?

Probably the most important benefit you get, before even digging deeper into configuration options and the API, is that the mobile user experience is much closer to a “native” feel.

Click Delay

The back and forward indicators (and the position indicators) in the Bootstrap Carousel suffer from what is known as “click delay”. A common problem on mobile touch devices is that clicking things like links is hampered by a 300ms delay. This is a problem caused by the mobile browser not knowing whether your tap on the screen is meant to perform an action, or if you’re in the process of double tapping to zoom in on some content (a common mobile browsing convention for zooming in on content that is not responsive, invented by Apple and replicated by every smartphone after them). So it mitigates this by enforcing a 300ms delay to determine your tap intention (you can read a more in-depth discussion of this topic here).

This may not sound like a big deal, but as I mentioned in the Bootstrap Loaders post, humans can perceive latency in as little as 100ms. 300ms leads a person to question whether their interaction even registered at all, and is a suboptimal user experience (imagine going through your mail on your smartphone, and every time you clicked an email it took 300ms to respond in any way – you’d probably drop the app, and the phone as well if everything were like that).

In Flexslider, click delay is not an issue. When on mobile, Flexslider uses touch events to control forward, back and positional navigation. This way the latency is non-existent and the interaction is immediate – your carousel moves forward and back as soon as the user taps it.

Swipe to navigate

In addition, a common pattern users have come to expect on mobile is the ability to swipe through things. It has become a natural expectation that many elements you interact with are capable of receiving, understanding and reacting to swiping and dragging gestures. With Bootstrap, the functionality is absent. With Flexslider, the user’s gesture registers immediately and can be used to either swipe quickly through items, or slowly drag between them.

Animations

The animations in Flexslider feel more natural than the Bootstrap equivalent and the position indicators give a more interactive feel to the items when clicked.

The first point is around the way we animate in between slides in our carousel, which has to do with what the animations “easing” is. “easing” basically has to do with how objects move – the Bootstrap easing is “linear”, meaning the animation progresses at a constant pace. Since most things don’t move that way (at a constant pace), it doesn’t feel as natural. It doesn’t feel “wrong”, but when we see the Flexslider animation in comparison, there’s a more fluid and understandable feel to it. The Flexslider easing is called “swing”, and it means the animation progresses slower at the beginning and end (you can see examples of lots of different easings here. I think “easeQuadOut” is the equivalent of “swing” in this case).

The second point is about how the positional indicators work. If you have more than two slides in your carousel, Bootstrap never changes the positional indicator behavior. I’m on the first slide and I click the third slide, I’m animated automatically to the third slide. There’s no sense of movement or position in the animation. In addition, it’s somewhat confusing if i’ve gone through all the slides, because casually sliding in the third slide in this case causes me to wonder what happened to the second slide – we’ve bypassed it entirely. In Flexslider, the slides are all quickly animated through, so you see that you’re actually progressing back to the first slide rather than being immediately transported there.

These might be more a matter of preference, but I think the difference is noticeable and an improvement to the experience.

Digging Deeper into Flexslider

For me, the improved mobile experience around gestures and tapping would be enough to warrant using Flexslider over Bootstrap. But i’ll talk about a few more configurations and API pieces before leaving the rest of the exploration to the reader.

An Example

$('.flexslider').flexslider({
  animation: 'fade',
  selector: '.slides div.slide',
  end: function () { alert('last slide!'); }
});

Here we’re modifying just a few options to add/change some functionality.

animation allows you to specify how the slides will animation. While not wildly expansive, you can choose “fade” in addition to “slide”.

selector lets you change some of the convention aspect of Flexslider. The convention is to specify a list item li, but here you can modify things so more types of markup are capable of being slides.

end is one of several events, in this case being fired when the carousel reaches the last slide. It’s useful for a plugin to have points to hook into throughout its lifecycle – you’ll inevitably find yourself in a place where knowing the state of your plugin is important due to a project requirement.

Flexslider comes with many, many options, but you don’t need to worry about them until you need them. I’d approach it in the simpler form to start, and add more capabilities when necessary. You can see the Flexslider homepage for more interactive examples.

Slick

“the last carousel you’ll ever need”

While probably not the last carousel you’ll ever need, since I learned about Slick it is becoming my new favorite option.

As with Bootstrap and Flexslider, let’s start off by looking at a markup example.

<div id="slick-carousel">
  <div><img src="slide-1.jpg"/></div>
  <div><img src="slide-2.jpg"/></div>
  <div><img src="slide-3.jpg"/></div>
</div>

It seems we’re getting progressively simpler. In the case of Slick we have even less to define and even more convention than Flexslider. The conventional Slick setup contains the following pieces.

A container element of some kind. Since we hand the element to the Slick API, it doesn’t really matter what it is, and it doesn’t require any special classes.

div elements to indicate the slides inside. This was something of a strange convention to me since I think of li elements when thinking of slides, but it’s the default. No extra classes required, it just finds the child elements and makes them slides.

After that, we initialize it with a call to the Slick API. We’ll include the dots configuration here to be consistent with Bootstrap and Flexslider (it’s disabled by default).

$('#slick-carousel').slick({
  dots: true
});

Again, we have an experience similar to Bootstrap, and now Flexslider – forward and back navigation, responsive sizing and position indicators.

See the Pen Slick Carousel by JP Camara (@jpcamara) on CodePen.

So surely we’re hitting an impass? Bootstrap was ok. Flexslider was alot better. How could Slick be better than what we’ve seen so far?

A Plethora of options

Slick is highly configurable. Not only does it have a lot of options, it also comes with additional functionality that neither Flexslider or Bootstrap offer.

Responsive Display

Flexslider and Bootstrap come with fairly basic responsive capabilities. Bootstrap gets smaller or larger as your shrink or expand your screen size. Flexslider does the same but also offers some variability in the width and margins of its slides, making it seem a bit more responsively flexible. But Slick takes this configuration to a totally different level.

Slick allows you to setup a responsive configuration property, which takes an array of objects defining how it is supposed to behave at any breakpoint you define.

$('#slick-carousel').slick({
  slidesToShow: 5,
  responsive: [{
    breakpoint: 1024,
    settings: {
      slidesToShow: 3,
      dots: true
    }
  }, {
    breakpoint: 480,
    settings: {
      slidesToShow: 1
    }
  }]
});

In this example, we’re specifying a responsive array that contains an object for each breakpoint where we want a different behavior. Inside the object we define a breakpoint property. Effectively we are creating javascript media queries, and these allow us to change how the Slick carousel behaves at each breakpoint. In this example i’m saying that above 1024, I want to show 5 slides, at 1024 and below I want to show 3 slides and show dots, and at 480 and below I want to show 1 slide with no dots.

Your responsive control is virtually limitless in this case. You have as much control over how your carousel works as you have over how your CSS does. Every option you’ve specified as the base of your Slick carousel can be configured at the different responsive levels.

Drag on Desktop

Sometimes, even in a Desktop browser, you want to drag between images in a carousel. At the time of writing this, the Flexslider folks aren’t particularly interested in that feature, so if you want desktop dragging between carousel items you’re out of luck with them.

With Slick, it’s enabled by default. This may not seem immediately useful, but there are lots of use cases. For one thing, users used to mobile interaction sometimes bleed that mental model into the browser, expecting things to work similarly between the two. Another example would be where you aren’t creating a carousel for the standard “slide through a bunch of images or text” experience – perhaps your carousel is meant to act like a timeline where users can drag between events. In these cases, you have so many features that work for your use case (forward and next, moving to points in the future or past, fluid transitions and good mobile interaction), and all that might remain to you is the desktop dragging behavior. Slick has you covered.

Lazy Loading

Slick also has some support for out of the box lazy loading. It’s a simple setup, and requires a couple additional configuration options.

<div id="slick-carousel">
  <div><img data-lazy="slide-1.jpg"/></div>
  <div><img data-lazy="slide-2.jpg"/></div>
  <div><img data-lazy="slide-3.jpg"/></div>
</div>
$('#slick-carousel').slick({
  lazyLoad: 'ondemand'
});

Our img tags now have data-lazy data attributes, instead of a src attribute. If you included the src attribute, the image would always load regardless of your intent. This way Slick can pull the attribute out and apply it to src at the appropriate time.

Our Slick initialization now has a lazyLoad option. Supply ‘ondemand’ for it to load the images as you progress through the carousel.

Considering that web page size has been on the rise and 56% of page size tends to come from images – lazy loading is a nice option to have with little to no additional effort.

Digging into Slick

Slick has way more options and features than i’ve mentioned here, so check out the demos it offers for some more impressive functionality. I’ve just offered a few features that i’ve found useful recently – there’s plenty more to try out.

Angular

For the angular inclined, here are some options for Slick and Flexslider.

Slick: https://github.com/vasyabigi/angular-slick

Flexslider: https://github.com/thenikso/angular-flexslider

Conclusion

We want to make websites that work great on all devices. We want to be responsive and capable and we want the interaction to be natural. Working with the Bootstrap Carousel our options are limited (by design) and our mobile interaction is bare. We can do better. With Flexslider and Slick we can create a Carousel experience that feels native and responsive to the user.

Have any of your own suggestions? Have a qualm with Carousels in general? Let me know in the comments.

Series Navigation<< Better Than Bootstrap Javascript: LoadersBetter Than Bootstrap Javascript: Click Delay >>
  • Peter Burford

    I like your writing style, it made it a pleasure to read. Great content, I have been looking for alternatives to Bootstrap

  • Very in-depth article. I knew Slick was better, but you really sold me on why! Nice work.