Responsive Product Slider Html Css Codepen Work

Key CSS features employed:

  • Scroll Snap: scroll-snap-type: x mandatory on the track and scroll-snap-align: start on cards ensures smooth paging.
  • Overflow & Touch Behavior: overflow-x: auto with -webkit-overflow-scrolling: touch for native mobile swipe.
  • Before diving into the code, let's understand the "why":

    This script calculates how many cards fit on screen, updates the track position, and handles responsive resize events.

    document.addEventListener('DOMContentLoaded', () => 
      const track = document.querySelector('.slider-track');
      const prevBtn = document.querySelector('.prev-btn');
      const nextBtn = document.querySelector('.next-btn');
      const trackWrapper = document.querySelector('.slider-track-wrapper');
      const dotsContainer = document.querySelector('.dots-container');
    

    let currentIndex = 0; let cardWidth = 0; let gap = 24; // 1.5rem in pixels (default) let cardsPerView = 0; let totalCards = 0; let maxIndex = 0;

    // Function to get the current card dimensions dynamically function updateDimensions() responsive product slider html css codepen work

    function updateSliderPosition() const offset = -currentIndex * (cardWidth + gap); track.style.transform = translateX($offsetpx); updateButtonsState();

    function updateButtonsState() prevBtn.disabled = currentIndex === 0; nextBtn.disabled = currentIndex >= maxIndex; prevBtn.style.opacity = prevBtn.disabled ? '0.5' : '1'; nextBtn.style.opacity = nextBtn.disabled ? '0.5' : '1';

    function updateDots() if (!dotsContainer) return; const dotCount = maxIndex + 1; dotsContainer.innerHTML = ''; for (let i = 0; i < dotCount; i++) const dot = document.createElement('button'); dot.classList.add('dot'); if (i === currentIndex) dot.classList.add('active'); dot.addEventListener('click', () => currentIndex = i; updateSliderPosition(); updateDots(); ); dotsContainer.appendChild(dot);

    // Event listeners nextBtn.addEventListener('click', () => if (currentIndex < maxIndex) currentIndex++; updateSliderPosition(); updateDots(); ); Key CSS features employed:

    prevBtn.addEventListener('click', () => if (currentIndex > 0) currentIndex--; updateSliderPosition(); updateDots(); );

    // Responsive: recalc on window resize let resizeTimer; window.addEventListener('resize', () => clearTimeout(resizeTimer); resizeTimer = setTimeout(() => updateDimensions(); , 150); );

    // Initial setup updateDimensions();

    // Optional: Touch/swipe support for mobile let touchStartX = 0; trackWrapper.addEventListener('touchstart', (e) => touchStartX = e.touches[0].clientX; ); Scroll Snap : scroll-snap-type: x mandatory on the

    trackWrapper.addEventListener('touchend', (e) => const touchEndX = e.changedTouches[0].clientX; const diff = touchEndX - touchStartX; if (Math.abs(diff) > 50) if (diff > 0 && currentIndex > 0) currentIndex--; else if (diff < 0 && currentIndex < maxIndex) currentIndex++; updateSliderPosition(); updateDots(); ); );

    While this slider is

    Key CSS features employed:

  • Scroll Snap: scroll-snap-type: x mandatory on the track and scroll-snap-align: start on cards ensures smooth paging.
  • Overflow & Touch Behavior: overflow-x: auto with -webkit-overflow-scrolling: touch for native mobile swipe.
  • Before diving into the code, let's understand the "why":

    This script calculates how many cards fit on screen, updates the track position, and handles responsive resize events.

    document.addEventListener('DOMContentLoaded', () => 
      const track = document.querySelector('.slider-track');
      const prevBtn = document.querySelector('.prev-btn');
      const nextBtn = document.querySelector('.next-btn');
      const trackWrapper = document.querySelector('.slider-track-wrapper');
      const dotsContainer = document.querySelector('.dots-container');
    

    let currentIndex = 0; let cardWidth = 0; let gap = 24; // 1.5rem in pixels (default) let cardsPerView = 0; let totalCards = 0; let maxIndex = 0;

    // Function to get the current card dimensions dynamically function updateDimensions()

    function updateSliderPosition() const offset = -currentIndex * (cardWidth + gap); track.style.transform = translateX($offsetpx); updateButtonsState();

    function updateButtonsState() prevBtn.disabled = currentIndex === 0; nextBtn.disabled = currentIndex >= maxIndex; prevBtn.style.opacity = prevBtn.disabled ? '0.5' : '1'; nextBtn.style.opacity = nextBtn.disabled ? '0.5' : '1';

    function updateDots() if (!dotsContainer) return; const dotCount = maxIndex + 1; dotsContainer.innerHTML = ''; for (let i = 0; i < dotCount; i++) const dot = document.createElement('button'); dot.classList.add('dot'); if (i === currentIndex) dot.classList.add('active'); dot.addEventListener('click', () => currentIndex = i; updateSliderPosition(); updateDots(); ); dotsContainer.appendChild(dot);

    // Event listeners nextBtn.addEventListener('click', () => if (currentIndex < maxIndex) currentIndex++; updateSliderPosition(); updateDots(); );

    prevBtn.addEventListener('click', () => if (currentIndex > 0) currentIndex--; updateSliderPosition(); updateDots(); );

    // Responsive: recalc on window resize let resizeTimer; window.addEventListener('resize', () => clearTimeout(resizeTimer); resizeTimer = setTimeout(() => updateDimensions(); , 150); );

    // Initial setup updateDimensions();

    // Optional: Touch/swipe support for mobile let touchStartX = 0; trackWrapper.addEventListener('touchstart', (e) => touchStartX = e.touches[0].clientX; );

    trackWrapper.addEventListener('touchend', (e) => const touchEndX = e.changedTouches[0].clientX; const diff = touchEndX - touchStartX; if (Math.abs(diff) > 50) if (diff > 0 && currentIndex > 0) currentIndex--; else if (diff < 0 && currentIndex < maxIndex) currentIndex++; updateSliderPosition(); updateDots(); ); );

    While this slider is