This week I found myself needing to develop a progress bar attached to an image carousel. My carousel of choice is always Slick Slider.

After a quick search, I realised there probably wasn’t an out of the box solution, so I decided to build one using some basic jQuery and utilising some simple CSS.

This is all very simple stuff, so feel free to copy this into your project if you need it.

HTML

<div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100">

<span class="slider__label sr-only">

</div>

For accessibility reasons, notice we’ve added the role attribute, aria attributes (valuemin and valuemax) to help for screen readers as well as the label span which won’t be visible to normal users.

CSS ( or in this case some SCSS )

.progress {

display: block;

width: 100%;

height: 10px;

border-radius: 10px;

overflow: hidden;



background-color: #f5f5f5;

background-image: linear-gradient(to right, black, black);

background-repeat: no-repeat;

background-size: 0 100%; transition: background-size .4s ease-in-out;

}

The CSS is also very simple.

Adding the base background colour as #f5f5f5 makes the element appear like there is no progress, and then using the background-image property with a linear gradient means all we have to do is increase the background size in order to make the progress increase.

jQuery

$(document).ready(function() {

var $slider = $('.slider');

var $progressBar = $('.progress');

var $progressBarLabel = $( '.slider__label' );



$slider.on('beforeChange', function(event, slick, currentSlide, nextSlide) {

var calc = ( (nextSlide) / (slick.slideCount-1) ) * 100;



$progressBar

.css('background-size', calc + '% 100%')

.attr('aria-valuenow', calc );



$progressBarLabel.text( calc + '% completed' );

});



$slider.slick({

slidesToShow: 3,

slidesToScroll: 1,

speed: 400

});

});

Loading the script on document.ready negates the need to run the function using slick slider’s init event.

Using the beforeChange event call, and passing through the variables currentSlide and nextSlide from Slick Slider, we can calculate the progress by means of dividing the slide number by the total number of slides ( -1 because the slide number starts from 0 ) and multiplying it by 100.

Then applying these values to the progress bar and the screen reader text allows the progress bar to move.

The Completed Progress Bar

I’ve saved the above code in CodePen.

Let me know your thoughts, or if there is a better way of achieving the same goal.

Updates

peterunlustig22 recommended merging my two event functions into just the one…

Original

$('.slider').on('init', function(event, slick) {

// the init event must be declared before the

// carousel

var count = slick.slideCount;

var current = slick.currentSlide;

calcProgress( count, current );

}); $('.slider').on('afterChange', function(event, slick) {

var count = slick.slideCount;

var current = slick.currentSlide;

calcProgress( count, current );

});

Improved

$('.slider').on('init afterChange', function(event, slick) {

var count = slick.slideCount;

var current = slick.currentSlide;

calcProgress( count, current );

});

I had previously never come across naming multiple events within on the on function, but according to jQuery docs, Peter is spot on.

When I originally built the progress bar, I used a span element and altered the width to make the progress change.

However, Peter also made another valid point: why not just use a background colour on the main element?

Original

<div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100">

<span class="progress__true"></span>

<span class="slider__label sr-only">

</div>

Improved

<div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100">

<span class="slider__label sr-only">

</div>

I originally set up the calcProgress function, and then ran that function on the afterChange event. However as the post shows above, it’s much easier to merge these scripts and run them together.

Thanks again for your suggestions Peter. I’ve updated my post and CodePen accordingly.