Gallery✨ Premium

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.

CSSVerticalY-axis

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

Pickup slots for a click-and-collect order — the "Pickup" step of the basket — Vertical Slider example 1

① Pickup slots for a click-and-collect order — the "Pickup" step of the basket

WhenWhen picking the pickup time, the customer clicks the bottom arrow to move from 17:00 – 17:30 to 17:30 – 18:00; the "Confirm" button repeats the time on screen.
WhyTimes are read from top to bottom, like a diary: moving them up or down follows the order of the day. A single visible slot fits a narrow box next to the order summary.
Settings--vtsl-height:150px, --vtsl-ratio:auto, --vtsl-radius:12px, green arrows --vtsl-arrow-bg:#1b7a46 shrunk to 32 px by the scene CSS, data-slide="créneau" ("slot"). Text-only slides. Capture: click on the bottom arrow every 1.3 s.
Looks from an autumn collection on mobile — one outfit per screen — Vertical Slider example 2

② Looks from an autumn collection on mobile — one outfit per screen

WhenOn the phone, the shopper swipes up and the next look replaces the previous one, price and sizes included; the counter goes from "Look 1 / 4" to "Look 2 / 4".
WhyOn mobile the thumb naturally moves up: a vertical feed is the usual gesture for full-screen content, and a full-length figure uses the whole height without being cropped.
SettingsFull phone screen: --vtsl-height:100%, --vtsl-radius:22px 22px 0 0, no arrows in the HTML, photos as <img>, price tag at the bottom. Capture: the scene sends the real code a pointerdown then a pointerup 120 px higher (the white circle shows the gesture).
Steps to assemble a bookcase — online instructions from a furniture maker — Vertical Slider example 3

③ Steps to assemble a bookcase — online instructions from a furniture maker

WhenNext to the parts list, the instructions show one step at a time; a click on the bottom arrow lifts in the next step and the "Step 2 of 4" heading updates.
WhyInstructions are read top to bottom: bringing the next step in from below keeps that reading direction, and the drawing stays large since a single step fills the card.
Settings--vtsl-height:100% of the card, --vtsl-radius:10px, wood-coloured arrows --vtsl-arrow-bg:#a0612f moved to the right edge, data-slide="étape" ("step"). Each slide: drawing as <img>, title, instruction. Capture: click on the bottom arrow every 1.5 s.

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 with data-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 inert and aria-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.

Chrome 102+✓ Full (measured)
Firefox 112+✓ Full (measured)
Safari 15.5+✓ Full (measured in WebKit)
Edge 102+✓ Full (Chromium engine)
iOS Safari 15.5+✓ Not checked on a real device
Android Chrome 102+✓ Full (Chromium engine)

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):

index.html — structure
<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 / propertyDefaultEffect
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

It does, on the carousel's surface: 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.
No. The wheel scrolls the page, as everywhere else: hijacking it surprises visitors and traps them in the carousel. Arrows, ↑ ↓ and swiping are enough.
Dots Navigation slides the track from left to right and is driven by dots that lead straight to any image. Here the axis is vertical and you move one step at a time with two arrows, top and bottom.