Scroll snap
Horizontal/vertical scrollers.
Title = Slider with navigation arrows
Description =
Component Id = scroll-snap
Filter by type of conference
-
<div class='slider' data-slider> <ul class='slider__track' data-slider-track> <li> <div class='slide'>1</div> </li> <li> <div class='slide'>2</div> </li> <li> <div class='slide'>3</div> </li> <li> <div class='slide'>4</div> </li> <li> <div class='slide'>5</div> </li> <li> <div class='slide'>6</div> </li> <li> <div class='slide'>7</div> </li> </ul> <div class='slider__buttons'> <button class='slider__button' data-slider-prev disabled> Previous </button> <button class='slider__button' data-slider-next> Next </button> </div> </div>
-
const slider = document.querySelector('[data-slider]'); const track = slider.querySelector('[data-slider-track]'); const prev = slider.querySelector('[data-slider-prev]'); const next = slider.querySelector('[data-slider-next]'); if (track) { prev.addEventListener('click', () => { next.removeAttribute('disabled'); track.scrollTo({ left: track.scrollLeft - track.firstElementChild.offsetWidth, behavior: 'smooth', }); }); next.addEventListener('click', () => { prev.removeAttribute('disabled'); track.scrollTo({ left: track.scrollLeft + track.firstElementChild.offsetWidth, behavior: 'smooth', }); }); track.addEventListener('scroll', () => { const trackScrollWidth = track.scrollWidth; const trackOuterWidth = track.clientWidth; prev.removeAttribute('disabled'); next.removeAttribute('disabled'); if (track.scrollLeft <= 0) { prev.setAttribute('disabled', ''); } if (track.scrollLeft === trackScrollWidth - trackOuterWidth) { next.setAttribute('disabled', ''); } }); }
-
.slider { --slider-padding: 1rem; --slider-column-gap: 1rem; --slide-width: 25%; --slide-min-width: 15rem; position: relative; overflow: hidden; .slider__track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; padding-inline: var(--slider-padding); scroll-behavior: smooth; scrollbar-width: none; list-style-type: none; padding: 0; margin-right: calc(var(--slider-column-gap) * -1); > * { flex: 0 0 var(--slide-width); min-width: var(--slide-min-width); scroll-snap-align: start; scroll-snap-stop: always; padding-right: var(--slider-column-gap); } &::-webkit-scrollbar { display: none; } } .slider__buttons { margin-top: 1rem; [disabled] { opacity: 0.5; } } } .slide { aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center; width: 100%; border-radius: 1rem; background: #6c5ce7; color: #a29bfe; font-size: 3rem; font-weight: 700; }