12 / 22
All 22 in 22 Tailwind CSS Image Carousel
- 01Tailwind E-commerce Product Gallery Carousel with Thumbnails
- 02Tailwind Shop the Look Multi-Item Card Slider with Scroll Snap
- 03Tailwind Infinite Logo Scroller Marquee with No JavaScript
- 04Tailwind Product Colour Variant Picker Slider
- 05Tailwind Full-Screen Hero Slideshow with Auto Cross-Fade
- 06Tailwind Testimonial Card Carousel with Star Ratings
- 07Tailwind Meet the Team Profile Slider with Circular Portraits
- 08Tailwind Portfolio Gallery Slider with Hover Caption Reveal
- 09Tailwind Netflix-Style Content Row Carousel with Hover Expand
- 10Tailwind Magazine Split-Screen Article Slider
- 11Tailwind Onboarding Slider with Native CSS Scroll-Marker Dots
- 12Tailwind Vertical Image Carousel with Y-Axis Scroll Snap
- 13Tailwind 3D Coverflow Carousel with Perspective Transforms
- 14Tailwind Cross-Fade Image Slideshow with Manual Controls
- 15Tailwind Dual Opposite-Direction Marquee Slider
- 16Tailwind Dot Pagination Carousel with Target and Has Selectors
- 17Tailwind Prev / Next Arrow Carousel with Native Scroll Buttons
- 18Tailwind Before / After Image Comparison Slider
- 19Tailwind Accordion Expanding Image Panel Carousel
- 20Tailwind Autoplay Slider with Keyframe Track and Progress Bars
- 21Tailwind Zoom-on-Hover Image Gallery Slider
- 22Tailwind Parallax Text-Over-Image Story Slider
Tailwind Vertical Image Carousel with Y-Axis Scroll Snap
A carousel that scrolls up and down instead of left to right — sidebar widgets, story feeds, creative portfolios. Tailwind ships snap-y as readily as snap-x, so the only genuinely vertical concern is giving the scroller a height and stopping its scroll from chaining to the page.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tcar-12 w-full min-h-svh grid place-items-center bg-tcar12-bg font-tcar12-sans px-5 py-10" aria-label="Vertical image carousel">
<ul tabindex="0" role="group" aria-label="Gallery, scroll up and down" class="tcar12-scroller list-none w-[min(340px,100%)] h-[min(560px,80svh)] overflow-y-auto m-0 p-0 rounded-[20px] snap-y snap-mandatory [overscroll-behavior:contain] [scrollbar-width:none] shadow-[0_30px_60px_-34px_oklch(0_0_0/0.9)] focus-visible:outline-3 focus-visible:outline-tcar12-acc focus-visible:outline-offset-[3px]">
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-1/700/900" width="700" height="900" decoding="async" alt="Desert dunes at sunset" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Sahara, Morocco</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-2/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Glacier lagoon" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Jökulsárlón, Iceland</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-3/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Terraced rice fields" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Bali, Indonesia</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-4/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Autumn forest path" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Kyoto, Japan</span></li>
</ul>
</section><section class="tcar-12 w-full min-h-svh grid place-items-center bg-tcar12-bg font-tcar12-sans px-5 py-10" aria-label="Vertical image carousel">
<ul tabindex="0" role="group" aria-label="Gallery, scroll up and down" class="tcar12-scroller list-none w-[min(340px,100%)] h-[min(560px,80svh)] overflow-y-auto m-0 p-0 rounded-[20px] snap-y snap-mandatory [overscroll-behavior:contain] [scrollbar-width:none] shadow-[0_30px_60px_-34px_oklch(0_0_0/0.9)] focus-visible:outline-3 focus-visible:outline-tcar12-acc focus-visible:outline-offset-[3px]">
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-1/700/900" width="700" height="900" decoding="async" alt="Desert dunes at sunset" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Sahara, Morocco</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-2/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Glacier lagoon" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Jökulsárlón, Iceland</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-3/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Terraced rice fields" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Bali, Indonesia</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-4/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Autumn forest path" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Kyoto, Japan</span></li>
</ul>
</section>@import "tailwindcss";
@theme {
--color-tcar12-bg: #0e1513;
--color-tcar12-bg: oklch(0.18 0.015 170);
--color-tcar12-acc: #2dd4bf;
--color-tcar12-acc: oklch(0.78 0.13 180);
--font-tcar12-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-12 {
width: 100%;
min-height: 100svh;
}
.tcar-12 ::selection {
background: var(--color-tcar12-acc);
color: #062120;
}
.tcar12-scroller::-webkit-scrollbar {
display: none;
}
@media (prefers-reduced-motion: reduce) {
.tcar12-scroller {
scroll-behavior: auto;
}
}@import "tailwindcss";
@theme {
--color-tcar12-bg: #0e1513;
--color-tcar12-bg: oklch(0.18 0.015 170);
--color-tcar12-acc: #2dd4bf;
--color-tcar12-acc: oklch(0.78 0.13 180);
--font-tcar12-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-12 {
width: 100%;
min-height: 100svh;
}
.tcar-12 ::selection {
background: var(--color-tcar12-acc);
color: #062120;
}
.tcar12-scroller::-webkit-scrollbar {
display: none;
}
@media (prefers-reduced-motion: reduce) {
.tcar12-scroller {
scroll-behavior: auto;
}
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tcar12-bg: #0e1513;
--color-tcar12-bg: oklch(0.18 0.015 170);
--color-tcar12-acc: #2dd4bf;
--color-tcar12-acc: oklch(0.78 0.13 180);
--font-tcar12-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-12 {
width: 100%;
min-height: 100svh;
}
.tcar-12 ::selection {
background: var(--color-tcar12-acc);
color: #062120;
}
.tcar12-scroller::-webkit-scrollbar {
display: none;
}
@media (prefers-reduced-motion: reduce) {
.tcar12-scroller {
scroll-behavior: auto;
}
}@import "tailwindcss";
@theme {
--color-tcar12-bg: #0e1513;
--color-tcar12-bg: oklch(0.18 0.015 170);
--color-tcar12-acc: #2dd4bf;
--color-tcar12-acc: oklch(0.78 0.13 180);
--font-tcar12-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-12 {
width: 100%;
min-height: 100svh;
}
.tcar-12 ::selection {
background: var(--color-tcar12-acc);
color: #062120;
}
.tcar12-scroller::-webkit-scrollbar {
display: none;
}
@media (prefers-reduced-motion: reduce) {
.tcar12-scroller {
scroll-behavior: auto;
}
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Nothing about the vertical axis needs special handling in Tailwind:
snap-yis the sibling ofsnap-xandsnap-startis unchanged. The interesting utilities here are the two that have nothing to do with snapping — height andoverscroll-behavior. h-[min(560px,80svh)]usessvhrather than the original'svh: inside a mobile page the widget would otherwise be taller than the visible viewport whenever the URL bar is showing.- UI change from the CSS original: the caption scrim went from
rgba(6,10,9,.85)tooklch(0.15 0.01 170 / 0.9). Several of the placeholder photographs are bright at the bottom edge, where the original caption dropped close to 4:1.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Vertical Image Carousel with Y-Axis Scroll Snap
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-vertical-image-carousel-scroll-snap/
A carousel that scrolls up and down instead of left to right — sidebar widgets, story feeds, creative portfolios. Tailwind ships snap-y as readily as snap-x, so the only genuinely vertical concern is giving the scroller a height and stopping its scroll from chaining to the page.
## HTML
```html
<section class="tcar-12 w-full min-h-svh grid place-items-center bg-tcar12-bg font-tcar12-sans px-5 py-10" aria-label="Vertical image carousel">
<ul tabindex="0" role="group" aria-label="Gallery, scroll up and down" class="tcar12-scroller list-none w-[min(340px,100%)] h-[min(560px,80svh)] overflow-y-auto m-0 p-0 rounded-[20px] snap-y snap-mandatory [overscroll-behavior:contain] [scrollbar-width:none] shadow-[0_30px_60px_-34px_oklch(0_0_0/0.9)] focus-visible:outline-3 focus-visible:outline-tcar12-acc focus-visible:outline-offset-[3px]">
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-1/700/900" width="700" height="900" decoding="async" alt="Desert dunes at sunset" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Sahara, Morocco</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-2/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Glacier lagoon" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Jökulsárlón, Iceland</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-3/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Terraced rice fields" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Bali, Indonesia</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-4/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Autumn forest path" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Kyoto, Japan</span></li>
</ul>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar12-bg: #0e1513;
--color-tcar12-bg: oklch(0.18 0.015 170);
--color-tcar12-acc: #2dd4bf;
--color-tcar12-acc: oklch(0.78 0.13 180);
--font-tcar12-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-12 {
width: 100%;
min-height: 100svh;
}
.tcar-12 ::selection {
background: var(--color-tcar12-acc);
color: #062120;
}
.tcar12-scroller::-webkit-scrollbar {
display: none;
}
@media (prefers-reduced-motion: reduce) {
.tcar12-scroller {
scroll-behavior: auto;
}
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Vertical Image Carousel with Y-Axis Scroll Snap
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-vertical-image-carousel-scroll-snap/
A carousel that scrolls up and down instead of left to right — sidebar widgets, story feeds, creative portfolios. Tailwind ships snap-y as readily as snap-x, so the only genuinely vertical concern is giving the scroller a height and stopping its scroll from chaining to the page.
## HTML
```html
<section class="tcar-12 w-full min-h-svh grid place-items-center bg-tcar12-bg font-tcar12-sans px-5 py-10" aria-label="Vertical image carousel">
<ul tabindex="0" role="group" aria-label="Gallery, scroll up and down" class="tcar12-scroller list-none w-[min(340px,100%)] h-[min(560px,80svh)] overflow-y-auto m-0 p-0 rounded-[20px] snap-y snap-mandatory [overscroll-behavior:contain] [scrollbar-width:none] shadow-[0_30px_60px_-34px_oklch(0_0_0/0.9)] focus-visible:outline-3 focus-visible:outline-tcar12-acc focus-visible:outline-offset-[3px]">
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-1/700/900" width="700" height="900" decoding="async" alt="Desert dunes at sunset" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Sahara, Morocco</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-2/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Glacier lagoon" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Jökulsárlón, Iceland</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-3/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Terraced rice fields" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Bali, Indonesia</span></li>
<li class="relative h-full snap-start overflow-hidden"><img src="https://picsum.photos/seed/vert-4/700/900" width="700" height="900" loading="lazy" decoding="async" alt="Autumn forest path" class="size-full object-cover block"><span class="absolute inset-x-0 bottom-0 px-5 pt-10 pb-5 text-[15px] font-semibold text-white bg-[linear-gradient(transparent,oklch(0.15_0.01_170/0.9))]">Kyoto, Japan</span></li>
</ul>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar12-bg: #0e1513;
--color-tcar12-bg: oklch(0.18 0.015 170);
--color-tcar12-acc: #2dd4bf;
--color-tcar12-acc: oklch(0.78 0.13 180);
--font-tcar12-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-12 {
width: 100%;
min-height: 100svh;
}
.tcar-12 ::selection {
background: var(--color-tcar12-acc);
color: #062120;
}
.tcar12-scroller::-webkit-scrollbar {
display: none;
}
@media (prefers-reduced-motion: reduce) {
.tcar12-scroller {
scroll-behavior: auto;
}
}
```How this works
Height is the requirement. A vertical snap container with no height has nothing to snap within; h-[min(560px,80svh)] gives it a window, and each frame's h-full makes exactly one land at a time.
Scroll chaining is the bug you would ship. Without [overscroll-behavior:contain], reaching the last frame hands the gesture to the page and the user scrolls past the widget mid-swipe. One arbitrary property prevents it.
Captions are text over a scrim. Real <span>s, legible and indexable, not burned into the photograph.
Make it yours
- Window height: the
h-[min(560px,80svh)]on the scroller. - Looser feel:
snap-proximityinstead ofsnap-mandatory. - Caption position: move it to
top-0and flip the gradient. - Focus ring colour:
--color-tcar12-acc.
Gotchas — read before shipping
- No explicit height means no vertical snapping at all — the single most common mistake in this pattern.
- Each frame must be at least the scroller's height (
h-full), or two frames share the window and neither snaps cleanly. overscroll-behavior:contain, notnone:nonealso disables pull-to-refresh on some platforms, which users notice.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Vertical scroll-snap is as well supported as horizontal and overscroll-behavior is Baseline; the floor quoted is Tailwind v4's generated sheet.