Create an infinite scrolling content slider in JavaScript

In this article we’ll see how to create a content slider with infinite scrolling. With JavaScript we need to adopt a specific technique.

We’ll link the navigation buttons to the slides with a data attribute that will contain the numeric index of the current slide in the DOM.

Every time that index matches the last slide of the slider, we’ll clone the existing slides and append them to their container while also updating the slide index in the navigation buttons.

Let’s start by setting up the general structure:

function setUpslider(container = null) {
        if(!container) {
            return;
        }
        const widthFactor = 12;
        const baseWidth = container.offsetWidth;
        const slides = container.querySelectorAll('li');
        for(const slide of slides) {
            slide.style.width = `${baseWidth}px`;
        }
        container.querySelector('.slider-wrapper').style.minWidth = `${baseWidth * widthFactor}px`;
        const sliderNav = document.createElement('nav');
        sliderNav.className = 'slider-nav';
        for(let i = 0; i < slides.length; i++) {
            let btn = document.createElement('button');
            btn.type = 'button';
            btn.dataset.slide = i;
            btn.innerHTML = `<span>${i+1}</span>`;
            sliderNav.appendChild(btn);
        }
        container.appendChild(sliderNav);
    }

The hidden part of the slider extends in width so that the slides can be arranged in a single row. When clicking each button we can add a visual marker:

function handleActiveButton(container, btn) {
        if(!container) {
            return;
        }
        const nav = container.querySelector('.slider-nav');
        if(!nav) {
            return;
        } 
        const buttons = nav.querySelectorAll('button');
        for(const button of buttons) {
            button.classList.remove('active');
        }
        btn.classList.add('active');

    }

To create infinite scrolling we define a function that uses the current slide index to update the slider whenever the right condition is met, i.e. when we are on the last slide.

function handleInfiniteScroll(container, index) {
        if(!container) {
            return;
        }
        const slides = container.querySelectorAll('li');
        if((index + 1) === slides.length) {
            for(const slide of slides) {
                const copy = slide.cloneNode(true);
                copy.classList.add('cloned');
                slide.parentNode.appendChild(copy);
            }
            const cloned = container.querySelectorAll('.cloned');
            for(const clone of cloned) {
                clone.style.width = `${container.offsetWidth}px`;
            }
            const buttons = container.querySelectorAll('.slider-nav button');
            let start = parseInt(buttons[buttons.length - 1].dataset.slide, 10);
            for(const button of buttons) {
                start++;
                button.dataset.slide = start;
            }
        }
    }

The new indexing will start from the index of the last navigation button. So let’s manage the slide navigation:

function handleSliderNavigation(container = null) {
        if(!container) {
            return;
        }
        const nav = container.querySelector('.slider-nav');
        if(!nav) {
            return;
        }
        const buttons = nav.querySelectorAll('button');
        const wrapper = container.querySelector('.slider-wrapper');
        

        for(const button of buttons) {
            button.addEventListener('click', () => {
                const slides = wrapper.querySelectorAll('li');
                const idx = parseInt(button.dataset.slide, 10);
                const slide = slides[idx];
                if(slide) {
                    const left = slide.offsetLeft;
                    const rule = `translateX(-${left}px)`;
                    wrapper.style.transform = 'translateX(0)';
                    wrapper.style.transform = rule;
                    handleActiveButton(container, button);
                    handleInfiniteScroll(container, idx);
                    
                }
            });
        }
    }

Finally, let’s initialize the code as follows:

document.addEventListener('DOMContentLoaded', () => {
        const slider = document.querySelector('.slider');
        setUpslider(slider);
        handleSliderNavigation(slider);
});

Demo

JavaScript Infinite Content Slider

Conclusion

An infinite slider is nothing more than a container whose descendants are cloned when the last slide of the list is reached. It’s a JavaScript technique that is not overly complex to implement.

Back to top