Vertical Slider
Vertical carousel: the track moves up or down one slide at a time, with an arrow at the top, one at the bottom, the ↑ ↓ keys and a vertical swipe.
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
The .vtsl-track is a column (flex-direction: column): slides sit one below the other, each 100% as tall as the frame. Moving on means applying translateY(-100%), -200%…; the 0.5 s transition brings the next image up from the bottom. Going back brings it down again. After the last one, the bottom button returns to the first by sliding the whole track back down.
Controls sit on the axis: the .vtsl-prev button at the top centre, .vtsl-next at the bottom, with chevrons turned 90° (˄ and ˅). On the keyboard, ↑ and ↓ do the same while focus is inside the carousel. By finger or mouse, a vertical drag of more than 50 px changes the image: upwards for the next one, downwards for the previous one.
For that drag to work on mobile, the track has touch-action: pan-x: a vertical move started on the carousel does not scroll the page. So place it where users can scroll elsewhere (a dedicated phone screen, a reasonably sized card), not across the full height of a long page.
Photos go in as <img> inside the slides (cropped with object-fit: cover). Each .vtsl-carousel works alone; the script declares nothing on window and does not wire itself twice on a frame marked data-vtsl-ready.
Accessibility
- Roles: the frame is a
role="region"described as a "carousel"; each slide is a "slide" group named "1 of 5". For time slots or steps, change the word withdata-slide("slot", "step"). - Named buttons: "Previous slide" at the top, "Next slide" at the bottom; these labels can be rewritten on the buttons ("Earlier slot"…).
- Keyboard: ↑ and ↓ inside the carousel, Tab and Enter on the arrows; slides outside the frame are
inertandaria-hidden. - Announcement: a hidden
aria-live="polite"area reads "slide 3 of 5" after each change. - Reduced motion: the image changes without moving up or down under
prefers-reduced-motion: reduce; arrows, keys and finger stay active.
Browser compatibility
About 3.6 KB of JavaScript. Checked on 08/11/2026 in Chromium, Firefox and WebKit through Playwright: copy 2 driven with no effect on copy 1, script duplicated without error, Enter on the arrow then the ↓ key, vertical finger swipe at 390 px without scrolling the page (Chromium) and mouse drag, reduced motion. Minimum versions read from @mdn/browser-compat-data 8.1.8; inert is the most recent feature used.
Older than inert: the carousel works, but Tab can enter a hidden slide that holds a link. Safari 14 ignores aspect-ratio: set --vtsl-height. Without JavaScript, the first slide stays in place.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0168-root">
<div class="vtsl-carousel" role="region" aria-roledescription="carousel" aria-label="Slideshow" data-slide="slide" data-of="of">
<div class="vtsl-track">
<div class="vtsl-slide"><span class="vtsl-caption">Slide 1</span></div>
<div class="vtsl-slide"><span class="vtsl-caption">Slide 2</span></div>
<!-- … more div.vtsl-slide, stacked top to bottom -->
</div>
<button type="button" class="vtsl-arrow vtsl-prev" aria-label="Previous slide"><svg>…</svg></button>
<button type="button" class="vtsl-arrow vtsl-next" aria-label="Next slide"><svg>…</svg></button>
</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 |
|---|---|---|
Height (CSS — --vtsl-height on .fx-0168-root) |
auto (from the format) | For a component: 150px; to fill a screen: 100%. |
Maximum width and format (CSS — --vtsl-width, --vtsl-ratio) |
640px · 16 / 10 | A portrait format (9 / 16) suits fashion photos or a stories-style feed. |
Duration (CSS — --vtsl-duration) |
0.5s | Time for the track to move up or down. |
Arrows (CSS — --vtsl-arrow-bg) |
white at 20% | A solid colour on a light background; their position is changed through .vtsl-prev (top) and .vtsl-next (bottom). |
Corners (CSS — --vtsl-radius) |
1rem | Accepts several values (22px 22px 0 0). |
Surrounding area (CSS — --vtsl-stage-bg, --vtsl-stage-padding, --vtsl-stage-min-height) |
#0a0a0f · 25px 16px · 300px | Dark demo frame, to reset to transparent, 0, 0. |
Spoken words (HTML — data-slide, data-of, aria-label) |
slide · of · Slideshow | "slot 2 of 5", "step 3 of 4"… depending on the content. |
FAQ
touch-action: pan-x keeps vertical moves for the carousel there. Outside the frame, the page scrolls normally. So keep a reasonable height or a dedicated screen; for a carousel that must not capture the finger, remove that line and the vertical drag will only work with the mouse.