Thumbnail navigation
Click any thumbnail to jump to that slide. The active thumbnail gets highlighted automatically.
1
2
3
4
5
View code
<div id="my-slider">
<div class="demo-slide s-purple">1</div>
<div class="demo-slide s-blue">2</div>
<div class="demo-slide s-green">3</div>
<div class="demo-slide s-amber">4</div>
<div class="demo-slide s-red">5</div>
</div>
<div id="my-thumbs">
<div class="thumb s-purple">1</div>
<div class="thumb s-blue">2</div>
<div class="thumb s-green">3</div>
<div class="thumb s-amber">4</div>
<div class="thumb s-red">5</div>
</div> .demo-slide { height: 260px; display:flex; align-items:center; justify-content:center; font-size:2.5rem; font-weight:700; color:#fff; border-radius:8px; }
#my-thumbs { display:flex; gap:8px; margin-top:12px; }
.thumb { flex:1; height:56px; border-radius:6px; display:flex; align-items:center; justify-content:center; font-weight:700; color:#fff; opacity:0.4; transition:opacity .2s; }
.sliderkit__thumb--active { opacity:1; outline:3px solid #6C2BD9; outline-offset:2px; } .demo-slide { height: 260px; display:flex; align-items:center; justify-content:center; font-size:2.5rem; font-weight:700; color:#fff; border-radius:8px; }
#my-thumbs { display:flex; gap:8px; margin-top:12px; }
.thumb { flex:1; height:56px; border-radius:6px; display:flex; align-items:center; justify-content:center; font-weight:700; color:#fff; opacity:0.4; transition:opacity .2s; }
.sliderkit__thumb--active { opacity:1; outline:3px solid #6C2BD9; outline-offset:2px; } import { Slider } from '@andresclua/sliderkit'
import { thumbs } from '@andresclua/sliderkit-plugins'
new Slider('#my-slider', {
items: 1,
loop: false,
speed: 300,
plugins: [thumbs({ container: '#my-thumbs' })],
}) Many thumbnails with arrow navigation
When you have more thumbnails than fit in view, add prev/next arrows to scroll the strip. The strip auto-scrolls to keep the active thumbnail visible.
View code
<div id="my-slider">
<div class="demo-slide s-purple">1</div>
<div class="demo-slide s-blue">2</div>
<div class="demo-slide s-green">3</div>
<div class="demo-slide s-amber">4</div>
<div class="demo-slide s-red">5</div>
<div class="demo-slide s-pink">6</div>
<div class="demo-slide s-teal">7</div>
<div class="demo-slide s-indigo">8</div>
<div class="demo-slide s-purple">9</div>
<div class="demo-slide s-blue">10</div>
</div>
<div class="thumb-nav">
<button class="thumb-arrow thumb-arrow--prev">←</button>
<div class="thumb-viewport">
<div id="my-thumbs">
<div class="thumb s-purple">1</div>
<div class="thumb s-blue">2</div>
<div class="thumb s-green">3</div>
<div class="thumb s-amber">4</div>
<div class="thumb s-red">5</div>
<div class="thumb s-pink">6</div>
<div class="thumb s-teal">7</div>
<div class="thumb s-indigo">8</div>
<div class="thumb s-purple">9</div>
<div class="thumb s-blue">10</div>
</div>
</div>
<button class="thumb-arrow thumb-arrow--next">→</button>
</div> .demo-slide { height:260px; display:flex; align-items:center; justify-content:center; font-size:2.5rem; font-weight:700; color:#fff; border-radius:8px; }
.thumb-nav { display:flex; align-items:center; gap:8px; margin-top:12px; }
.thumb-viewport { flex:1; overflow:hidden; }
#my-thumbs { display:flex; gap:8px; }
.thumb { flex:0 0 72px; height:56px; border-radius:6px; display:flex; align-items:center; justify-content:center; font-weight:700; color:#fff; opacity:0.4; transition:opacity .2s; }
.sliderkit__thumb--active { opacity:1; outline:3px solid #6C2BD9; outline-offset:2px; }
.thumb-arrow { width:32px; height:32px; border-radius:50%; border:1px solid #e2e8f0; background:#fff; cursor:pointer; font-size:1rem; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
.thumb-arrow:hover { background:#f3f4f6; } .demo-slide { height:260px; display:flex; align-items:center; justify-content:center; font-size:2.5rem; font-weight:700; color:#fff; border-radius:8px; }
.thumb-nav { display:flex; align-items:center; gap:8px; margin-top:12px; }
.thumb-viewport { flex:1; overflow:hidden; }
#my-thumbs { display:flex; gap:8px; }
.thumb { flex:0 0 72px; height:56px; border-radius:6px; display:flex; align-items:center; justify-content:center; font-weight:700; color:#fff; opacity:0.4; transition:opacity .2s; }
.sliderkit__thumb--active { opacity:1; outline:3px solid #6C2BD9; outline-offset:2px; }
.thumb-arrow { width:32px; height:32px; border-radius:50%; border:1px solid #e2e8f0; background:#fff; cursor:pointer; font-size:1rem; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
.thumb-arrow:hover { background:#f3f4f6; } import { Slider } from '@andresclua/sliderkit'
import { thumbs } from '@andresclua/sliderkit-plugins'
const slider = new Slider('#my-slider', {
items: 1,
loop: false,
speed: 300,
plugins: [
thumbs({ container: '#my-thumbs' }),
],
})
const viewport = document.querySelector('.thumb-viewport')
const strip = document.getElementById('my-thumbs')
// arrow buttons scroll the strip
document.querySelector('.thumb-arrow--prev').addEventListener('click', () => {
viewport.scrollBy({ left: -160, behavior: 'smooth' })
})
document.querySelector('.thumb-arrow--next').addEventListener('click', () => {
viewport.scrollBy({ left: 160, behavior: 'smooth' })
})
// auto-scroll to keep active thumb in view on slide change
slider.on('indexChanged', () => {
const active = strip.children[slider.activeIndex]
if (active) active.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' })
})
// drag-to-scroll on the thumbnail strip
let isDragging = false, dragStartX = 0, dragScrollLeft = 0
viewport.style.cursor = 'grab'
viewport.addEventListener('mousedown', (e) => {
isDragging = true
dragStartX = e.pageX - viewport.offsetLeft
dragScrollLeft = viewport.scrollLeft
viewport.style.cursor = 'grabbing'
})
viewport.addEventListener('mouseleave', () => { isDragging = false; viewport.style.cursor = 'grab' })
viewport.addEventListener('mouseup', () => { isDragging = false; viewport.style.cursor = 'grab' })
viewport.addEventListener('mousemove', (e) => {
if (!isDragging) return
e.preventDefault()
viewport.scrollLeft = dragScrollLeft - (e.pageX - viewport.offsetLeft - dragStartX)
}) Arrows navigate the slider
Same thumbnail strip, but now the prev/next arrows move the slider itself — the active thumbnail follows automatically.
View code
<div id="my-slider">
<div class="demo-slide s-purple">1</div>
<div class="demo-slide s-blue">2</div>
<div class="demo-slide s-green">3</div>
<div class="demo-slide s-amber">4</div>
<div class="demo-slide s-red">5</div>
<div class="demo-slide s-pink">6</div>
<div class="demo-slide s-teal">7</div>
<div class="demo-slide s-indigo">8</div>
<div class="demo-slide s-purple">9</div>
<div class="demo-slide s-blue">10</div>
</div>
<div class="thumb-nav">
<button class="thumb-arrow thumb-arrow--prev">←</button>
<div class="thumb-viewport">
<div id="my-thumbs">
<div class="thumb s-purple">1</div>
<div class="thumb s-blue">2</div>
<div class="thumb s-green">3</div>
<div class="thumb s-amber">4</div>
<div class="thumb s-red">5</div>
<div class="thumb s-pink">6</div>
<div class="thumb s-teal">7</div>
<div class="thumb s-indigo">8</div>
<div class="thumb s-purple">9</div>
<div class="thumb s-blue">10</div>
</div>
</div>
<button class="thumb-arrow thumb-arrow--next">→</button>
</div> .demo-slide { height:260px; display:flex; align-items:center; justify-content:center; font-size:2.5rem; font-weight:700; color:#fff; border-radius:8px; }
.thumb-nav { display:flex; align-items:center; gap:8px; margin-top:12px; }
.thumb-viewport { flex:1; overflow:hidden; }
#my-thumbs { display:flex; gap:8px; }
.thumb { flex:0 0 72px; height:56px; border-radius:6px; display:flex; align-items:center; justify-content:center; font-weight:700; color:#fff; opacity:0.4; transition:opacity .2s; cursor:pointer; }
.sliderkit__thumb--active { opacity:1; outline:3px solid #6C2BD9; outline-offset:2px; }
.thumb-arrow { width:32px; height:32px; border-radius:50%; border:1px solid #e2e8f0; background:#fff; cursor:pointer; font-size:1rem; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
.thumb-arrow:hover { background:#f3f4f6; } .demo-slide { height:260px; display:flex; align-items:center; justify-content:center; font-size:2.5rem; font-weight:700; color:#fff; border-radius:8px; }
.thumb-nav { display:flex; align-items:center; gap:8px; margin-top:12px; }
.thumb-viewport { flex:1; overflow:hidden; }
#my-thumbs { display:flex; gap:8px; }
.thumb { flex:0 0 72px; height:56px; border-radius:6px; display:flex; align-items:center; justify-content:center; font-weight:700; color:#fff; opacity:0.4; transition:opacity .2s; cursor:pointer; }
.sliderkit__thumb--active { opacity:1; outline:3px solid #6C2BD9; outline-offset:2px; }
.thumb-arrow { width:32px; height:32px; border-radius:50%; border:1px solid #e2e8f0; background:#fff; cursor:pointer; font-size:1rem; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
.thumb-arrow:hover { background:#f3f4f6; } import { Slider } from '@andresclua/sliderkit'
import { thumbs } from '@andresclua/sliderkit-plugins'
const slider = new Slider('#my-slider', {
items: 1,
loop: false,
speed: 300,
plugins: [thumbs({ container: '#my-thumbs' })],
})
const viewport = document.querySelector('.thumb-viewport')
const strip = document.getElementById('my-thumbs')
// arrows navigate the slider, not the strip
document.querySelector('.thumb-arrow--prev').addEventListener('click', () => slider.prev())
document.querySelector('.thumb-arrow--next').addEventListener('click', () => slider.next())
// auto-scroll strip to keep active thumb in view
slider.on('indexChanged', () => {
const active = strip.children[slider.activeIndex]
if (active) active.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' })
})
// drag-to-scroll on the thumbnail strip
let isDragging = false, dragStartX = 0, dragScrollLeft = 0
viewport.style.cursor = 'grab'
viewport.addEventListener('mousedown', (e) => {
isDragging = true
dragStartX = e.pageX - viewport.offsetLeft
dragScrollLeft = viewport.scrollLeft
viewport.style.cursor = 'grabbing'
})
viewport.addEventListener('mouseleave', () => { isDragging = false; viewport.style.cursor = 'grab' })
viewport.addEventListener('mouseup', () => { isDragging = false; viewport.style.cursor = 'grab' })
viewport.addEventListener('mousemove', (e) => {
if (!isDragging) return
e.preventDefault()
viewport.scrollLeft = dragScrollLeft - (e.pageX - viewport.offsetLeft - dragStartX)
})