Thumbnail Slider
A large view and a row of thumbnail buttons: a click, Enter or a drag on the image slides the view, and the active thumbnail gets a white frame.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Gallery has 44 effects, including 6 free. Explore the category →
3 usage examples



How it works
Inside .fx-0165-root, the .tsl-slider block stacks a .tsl-viewport window (2/1 format by default, rounded corners) and a .tsl-thumbs row. The window holds a .tsl-track where each .tsl-slide takes the full width; showing slide n means shifting the track by translateX(-n × 100%) in 0.5 s.
Each thumbnail is a real <button>: the n-th thumbnail shows the n-th slide (order makes the link, no index to write). The active thumbnail carries aria-current="true", which gives it full opacity and the white frame; the others stay at 50%. On the large view, a horizontal drag of more than 50 px with a finger or the mouse moves to the next or previous slide, looping, and the thumbnail follows.
Buyers' images go straight in: an <img> in a slide or a thumbnail covers it entirely (object-fit: cover). Without images, the five demo gradients show. The script handles each .fx-0165-root on the page separately: several galleries live side by side without interfering.
Accessibility
- Reachable thumbnails: native buttons, so Tab, Enter and Space work; each has a name ("Show slide 2") and the current one is flagged with
aria-current. White:focus-visibleoutline. - Carousel roles: a named
aria-roledescription="carousel"region; slides arerole="group"announced as "2 of 5". The track isaria-live="polite": the chosen slide is read out. - Hidden slides:
inert, so a link or button inside an image that isn't shown cannot take focus. - Reduced motion: under
prefers-reduced-motion: reducethe view changes without gliding; nothing else moves on its own. - Touch: Pointer Events and
touch-action: pan-yon the large view: a horizontal gesture changes photo, a vertical one scrolls the page.
Browser compatibility
Dependency-free JavaScript (Pointer Events, aria-current as a styling hook), aspect-ratio (Chrome 88, Firefox 89, Safari 15) and inert (Chrome 102, Firefox 112, Safari 15.5 according to MDN). Measured in Chromium 151, Firefox 153 and WebKit 26.5 (Playwright): two galleries with only the second one driven, thumbnails by keyboard, reduced motion, 390 px without overflow, finger swipe (Chromium) without blocking vertical scrolling, 0 errors.
Without JavaScript, the first image and the thumbnails show but the thumbnails do nothing. Without aspect-ratio (2020 browsers), the large view has no height: give it a fixed one.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0165-root">
<div class="tsl-slider" role="region" aria-roledescription="carousel" aria-label="…">
<div class="tsl-viewport">
<div class="tsl-track" aria-live="polite">
<div class="tsl-slide" role="group" aria-roledescription="slide" aria-label="1 of 5"><img src="…" alt="…"></div>
…
</div>
</div>
<div class="tsl-thumbs">
<button class="tsl-thumb" type="button" aria-label="…" aria-current="true"><img src="…" alt=""></button>
<button class="tsl-thumb" type="button" aria-label="…"><img src="…" alt=""></button>
…
</div>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Maximum width (CSS — --tsl-max-width) |
640px | The gallery takes its container's width up to this limit; none for the full width. |
Large view proportions (CSS — --tsl-ratio) |
2 / 1 | Width/height ratio of the window. Images are cropped to fill it. |
Thumbnail size (CSS — --tsl-thumb-w / --tsl-thumb-h) |
50px / 32px | Width and height of each thumbnail button. The row wraps when it runs out of room. |
Images (HTML — <img> in .tsl-slide and .tsl-thumb) |
none: 5 gradients "Slide 1" to "Slide 5" | One image per slide and its smaller version in the thumbnail of the same rank. Keep as many thumbnails as slides. |
Thumbnail names (HTML — aria-label of .tsl-thumb) |
"Show slide 1"… | Text read by screen readers; describe what the image shows ("Arch cover"). |
Active thumbnail (CSS — .tsl-thumb[aria-current="true"]) |
opacity 1, 2 px #fff frame | Change the frame colour or the opacity of inactive thumbnails (0.5 by default). |
FAQ
.tsl-thumbs shows the 3rd .tsl-slide. To reorder, move the slide and its thumbnail together.<video>. Hidden slides are inert, but a playing video keeps playing: pause it yourself if you change slide during playback.