Introduction

In this tutorial, you'll learn how to control a carousel by basic APIs with creating the following gallery. When the main carousel moves, the active thumbnail will change. Also, thumbnails are clickable to navigate the main carousel.

HTML and CSS

First, let's write markup to create a carousel and thumbnails. Make sure to describe your images by alt:

<section id="main-carousel" class="splide" aria-label="My Awesome Gallery">
<div class="splide__track">
<ul class="splide__list">
<li class="splide__slide">
<img src="image1.jpg" alt="">
</li>
<li class="splide__slide">
<img src="image2.jpg" alt="">
</li>
<li class="splide__slide">
<img src="image3.jpg" alt="">
</li>
<li class="splide__slide">
<img src="image4.jpg" alt="">
</li>
</ul>
</div>
</section>
<ul id="thumbnails" class="thumbnails">
<li class="thumbnail">
<img src="thumbnail1.jpg" alt="">
</li>
<li class="thumbnail">
<img src="thumbnail2.jpg" alt="">
</li>
<li class="thumbnail">
<img src="thumbnail3.jpg" alt="">
</li>
<li class="thumbnail">
<img src="thumbnail4.jpg" alt="">
</li>
</ul>
HTML

Then, style thumbnails as you like. This example uses this CSS:

.thumbnails {
display: flex;
margin: 1rem auto 0;
padding: 0;
justify-content: center;
}
.thumbnail {
width: 70px;
height: 70px;
overflow: hidden;
list-style: none;
margin: 0 0.2rem;
cursor: pointer;
}
.thumbnail img {
width: 100%;
height: auto;
}
CSS

Next, apply Splide to the main carousel. This example disables pagination because the carousel will have the thumbnail control:

var splide = new Splide( '#main-carousel', {
pagination: false,
} );
splide.mount();
JavaScript

Thumbnails

Okay, the most important part is coming 💪

To make thumbnails clickable, we need to listen to their click events:

// Collects LI elements:
var thumbnails = document.getElementsByClassName( 'thumbnail' );
for ( var i = 0; i < thumbnails.length; i++ ) {
initThumbnail( thumbnails[ i ], i );
}
// The function to initialize each thumbnail.
function initThumbnail( thumbnail, index ) {
thumbnail.addEventListener( 'click', function () {
// move the carousel
} );
}
JavaScript

When the user clicks thumbnail, the main carousel should move to the corresponded slide. You can move the carousel via Splide#go() that can take a slide index:

var splide = new Splide( ... );
...
function initThumbnail( thumbnail, index ) {
thumbnail.addEventListener( 'click', function () {
splide.go( index );
} );
}
JavaScript

Now we can navigate the carousel by clicking thumbnails, but the user won't be sure which thumbnail is currently selected. To emphasize it by CSS, let's add the is-active class to the active thumbnail. You can toggle the class by listening to 'move' event triggered every time when the carousel moves:

var thumbnails = document.getElementsByClassName( 'thumbnail' );
var current; // Keeps the current thumbnail
...
splide.on( 'move', function () {
if ( current ) {
current.classList.remove( 'is-active' );
}
// Splide#index returns the latest slide index:
var thumbnail = thumbnails[ splide.index ];
if ( thumbnail ) {
thumbnail.classList.add( 'is-active' );
current = thumbnail;
}
} );
JavaScript

The current variable holds the current thumbnail element so that we can remove is-active when it changes.

By using the is-active class, we can clarify the selected thumbnail like so:

.thumbnail {
...
opacity: 0.3;
}
.thumbnail.is-active {
opacity: 1;
}
CSS

That's better — but as we add the class when the carousel moves, no slide is active initially. We can fix it by the mounted event fired right after the carousel is initialized:

splide.on( 'mounted move', function () {
...
} );
JavaScript

We're done! 🎉 Here is the whole code of this tutorial:

var splide = new Splide( '#main-carousel', {
pagination: false,
} );
var thumbnails = document.getElementsByClassName( 'thumbnail' );
var current;
for ( var i = 0; i < thumbnails.length; i++ ) {
initThumbnail( thumbnails[ i ], i );
}
function initThumbnail( thumbnail, index ) {
thumbnail.addEventListener( 'click', function () {
splide.go( index );
} );
}
splide.on( 'mounted move', function () {
var thumbnail = thumbnails[ splide.index ];
if ( thumbnail ) {
if ( current ) {
current.classList.remove( 'is-active' );
}
thumbnail.classList.add( 'is-active' );
current = thumbnail;
}
} );
splide.mount();
JavaScript

This sample code is available in CodeSandbox too.

This gallery is not compatible with the destroy option because Splide discards all handlers on destruction. You need to create an extension to make it work with the option.

Tips

I highly recommend improving accessibility by implementing these things:

  • Assign tabindex="0" to thumbnails for keyboard users
  • Add aria-label to tell what happens when the user clicks each thumbnail (aria-label="Go to slide 1").
  • Add aria-current to the active thumbnail
  • Link thumbnails to each slide by aria-controls