Blog

JavaScript

Posted on — Last updated on August 29, 2021

How to create a simple image slider with jQuery

Let’s build a simple Image Slideshow with jQuery from scratch. No plugins!

One of the most popular web components that you can find in most websites out there nowadays is the slideshow, a collection of key site related information: things like e-commerce products, portfolio items, latest news, sponsored ads – you name it.

Also known as sliders or carousels, slideshows are popular because they allow to effectively display a lot of information on a website in a compact and organized manner.

In case you don’t know what I’m talking about, this is what a slideshow is.

Before we start

Why would we want to build a slideshow from scratch instead of relying on third-party plugins? Well, that’s because:

  1. It’s really easy to do.
  2. We also keep the number of HTTP requests to a minimum as we aren’t loading unnecessary third-party JavaScript / CSS files, helping our site load much faster.
  3. Third-party plugins are often left abandoned by their authors for a variety of reasons. If that happens and your slider breaks or bugs out occasionally/all the time then you’re on your own.

Plus, you get to choose how your slideshow looks and behaves. If you’re like me and you love building/creating stuff it doesn’t get any more DIY than this.

So, without futher ado, let’s get to work!

The HTML Markup

To build our slideshow, we’re going to need the following elements:

  • A container element to, err, contain our slides.
  • Pagination buttons to move back and forth between slides.
  • A list of slides, each with its own background image and caption.

This is our container element:

<div id="jquery-slideshow-container">
    <!-- Our slider goes here -->
</div>

Pretty simple, huh?

Next, our list of slides:

<div id="jquery-slideshow-container">

    <ul id="jquery-slideshow">
        <li style="background-image: url(path/to/background-image-1.jpg);">
            <a href="https://www.example.com/some-page">
                <span>Caption for slide #1 goes here.</span>
            </a>
        </li>
        <li style="background-image: url(path/to/background-image-2.jpg);">
            <a href="https://www.example.com/another-page">
                <span>Caption for slide #2 goes here.</span>
            </a>
        </li>
        <li style="background-image: url(path/to/background-image-3.jpg);">
            <a href="https://www.example.com/lorem-ipsum-page">
                <span>Caption for slide #3 goes here.</span>
            </a>
        </li>
        <!-- More slides here ... -->
    </ul>

</div>

You may be asking yourself “What about the pagination links, Héctor? I don’t see them.” Don’t worry, we’ll get to that soon.

Now that we have our HTML markup almost complete, let’s focus now on styling our slider.

Styling the Slider

To achieve the carousel effect we want our container to show only one slide at a time while the rest remains hidden from view.

In order to do so we’ll use the following CSS styles:

#jquery-slideshow-container {
    overflow: hidden;
    position: relative;
    width: 100%;
    height: 300px;
}

We also need our list of sliders to be able to move freely inside our container, so:

#jquery-slideshow-container #jquery-slideshow {
    overflow: hidden;
    position: relative;
    top: 0;
    left: 0;
    margin: 0;
    padding: 0;
    height: 100%;
}

With that out of the way, let’s style our slides. We want them positioned next to each other so the transition between them is clean. Also, we want the background images to be centered and have them cover the entire slide.

Here’s how we do it:

#jquery-slideshow-container #jquery-slideshow li {
    display: inline;
    float: left;
    margin: 0;
    padding: 0;
    list-style: none;
    height: 100%;
    background-position: 50% 50%;
    background-repeat: no-repeat;
    background-size: cover;
}

Finally, we’re going to style our caption:

/* Let's have our A tag fill the entire slide */
#jquery-slideshow-container #jquery-slideshow li a {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
    color: #ffffff;
    transition: color 0.2s ease-in;
}

#jquery-slideshow-container #jquery-slideshow li a:hover {
    color: #ef233c;
}

    /* Position our caption at the bottom right corner of the slide */
    #jquery-slideshow-container #jquery-slideshow li a span {
        display: inline-block;
        position: absolute;
        right: 0;
        bottom: 0;
        padding: 0.75em 1.5em;
        font-size: 1.3em;
        background: #000000; /* fallback for old browsers */
        background: rgba(0, 0, 0, 0.8);
    }

If you refresh your page now you’ll notice that your slider won’t display anything. This is because the slides don’t have a defined width property.

The reason why I didn’t set a fixed width is because we want our slider to be responsive and to do that we’re going to use some JavaScript magic.

Bringing our Slider into life with jQuery

At this point we need to do a couple of things:

  1. Have our slider adapt itself to the available space automatically.
  2. Detect whether there are enough slides to display pagination buttons.

For this, as I mentioned earlier, we’re going to use jQuery. If you haven’t added it to your page yet you can do so either by downloading a copy of jQuery to your site or by loading it directly from Google’s Hosted Libraries.

Now, this little script is where the magic happens:

<script>
    jQuery(function($){

        var slider = $("#jquery-slideshow"), // cache the slider object for later use
            item_width = slider.parent().outerWidth(), // get the width of the container for later use
            timer = null; // will reference our autoplay() timer

        // Adjust the slider when/if the window gets resized
        $( window ).on( "resize", adjust );
        adjust();

        // We have more than one slide,
        // let's add the pagination buttons
        if ( slider.children("li").length > 1 ) {

            // Add previous/next buttons
            slider.parent().append("<a href=\"#\" id=\"btn-prev\"><i class=\"fa fa-angle-left\"></i><span>Previous</span></a><a href=\"#\" id=\"btn-next\"><i class=\"fa fa-angle-right\"></i><span>Next</span></a>");

            // Handle clicks on the next button
            slider.parent().on("click", "a#btn-prev", function(e){
                e.preventDefault();

                slider.children("li:last").prependTo( slider );
                slider.css("left", -item_width);

                slider.animate({
                    left: 0
                }, 300, "swing");
            });

            // Handle clicks on the previous button
            slider.parent().on("click", "a#btn-next", function(e){
                e.preventDefault();

                slider.animate({
                    left: -item_width
                }, 300, "swing", function(){
                    slider.children("li:first").appendTo( slider );
                    slider.css("left", 0);
                });
            });
        }

        // Autoplay slider (but only when the window/tab is active
        // to save resources)
        document.addEventListener("visibilitychange", function() {
            if ( "undefined" !== typeof document.hidden && document.hidden ) {
                clearInterval(timer);
                timer = null;
            } else {
                autoplay();
            }
        }, false);

        // Pause/resume autoplay on hover in/out
        slider.hover(function(){
            if ( timer ) {
                clearInterval(timer);
                timer = null;
            }
        }, function(){
            autoplay();
        });

        // Helpers
        function autoplay(){
            if ( $("a#btn-next").length ) {
                timer = setInterval(function(){
                    $("a#btn-next").trigger("click");
                }, 5000);
            }
        }

        function adjust(){
            item_width = slider.parent().outerWidth();
            slider.children("li").width( item_width ).parent().width( item_width * slider.children("li").length );
        }

    });
</script>

Let me explain a little bit what’s going on:

  • Lines 9 and 10 take care of our first objective: have our slider adapt itself to the available space automatically. In line 9 we call the function adjust() (defined at the end of the script) which takes care of this.
  • Lines 14 to 42 check that we have enough slides to require the use of pagination buttons. If so, the script adds them to the DOM and defines the functions that will handle the click events.
  • Lines 46 to 53 and 63 to 72 animate the slider, having it display a different slide every 5 seconds.

With this you should have a working slider quite similar to the one at the beginning of this article, only difference being that your pagination buttons are text links instead of arrow buttons.

To give them the same look as the example above you’ll need Font Awesome for the arrow icons and the following CSS rules as well:

/* Vertically center our buttons */
#jquery-slideshow-container #btn-prev,
#jquery-slideshow-container #btn-next {
    position: absolute;
    top: 50%;
    z-index: 100;
    color: #ffffff;
    font-size: 4em;
    line-height: 1;
    text-shadow: 0px 1px 5px rgba(0, 0, 0, 0.3);
    transform: translateY(-50%);
}

#jquery-slideshow-container #btn-prev {
    left: 15px;
}

#jquery-slideshow-container #btn-next {
    right: 15px;
}

    /* hide the text links */
    #jquery-slideshow-container #btn-prev span,
    #jquery-slideshow-container #btn-next span {
        display: none;
    }

Et voilà!

Demo: jQuery slider in action!

Questions? Suggestions?

Leave a comment below if you have questions or even suggestions on how to improve this tutorial. And if you built something nice with it feel free to share so others can see it 🙂