02 / 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 Shop the Look Multi-Item Card Slider with Scroll Snap
A horizontal product-card rail: three to four cards on desktop, one-per-view on mobile — the 'complete the look' pattern. Tailwind ships first-class snap-x snap-mandatory / snap-start utilities, so this is the rare carousel where the port is shorter than the original, not just better located.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tcar-02 w-full min-h-svh grid place-items-center bg-tcar02-bg font-tcar02-sans px-3 py-10" aria-label="Shop the look product rail">
<div class="w-[min(760px,100%)]">
<h3 class="text-[15px] font-bold tracking-[0.02em] text-tcar02-ink mx-2 mb-3.5">Complete the look</h3>
<ul tabindex="0" role="group" aria-label="Recommended products, scrollable" class="list-none flex gap-4 overflow-x-auto px-2 pt-1.5 pb-4 m-0 snap-x snap-mandatory [scroll-padding-left:8px] [scrollbar-width:thin] [scrollbar-color:var(--color-tcar02-track)_transparent] focus-visible:outline-3 focus-visible:outline-tcar02-acc focus-visible:outline-offset-2 focus-visible:rounded-xl">
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-1/500/600" width="500" height="600" decoding="async" alt="Oversized wool coat" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Wool Overcoat</span><span class="text-sm font-bold text-tcar02-acc">$248</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-2/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Ribbed knit scarf" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Ribbed Scarf</span><span class="text-sm font-bold text-tcar02-acc">$54</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-3/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Leather ankle boots" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Ankle Boots</span><span class="text-sm font-bold text-tcar02-acc">$189</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-4/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Canvas crossbody bag" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Crossbody Bag</span><span class="text-sm font-bold text-tcar02-acc">$96</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-5/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Round tortoiseshell sunglasses" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Sunglasses</span><span class="text-sm font-bold text-tcar02-acc">$72</span></div>
</li>
</ul>
</div>
</section><section class="tcar-02 w-full min-h-svh grid place-items-center bg-tcar02-bg font-tcar02-sans px-3 py-10" aria-label="Shop the look product rail">
<div class="w-[min(760px,100%)]">
<h3 class="text-[15px] font-bold tracking-[0.02em] text-tcar02-ink mx-2 mb-3.5">Complete the look</h3>
<ul tabindex="0" role="group" aria-label="Recommended products, scrollable" class="list-none flex gap-4 overflow-x-auto px-2 pt-1.5 pb-4 m-0 snap-x snap-mandatory [scroll-padding-left:8px] [scrollbar-width:thin] [scrollbar-color:var(--color-tcar02-track)_transparent] focus-visible:outline-3 focus-visible:outline-tcar02-acc focus-visible:outline-offset-2 focus-visible:rounded-xl">
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-1/500/600" width="500" height="600" decoding="async" alt="Oversized wool coat" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Wool Overcoat</span><span class="text-sm font-bold text-tcar02-acc">$248</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-2/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Ribbed knit scarf" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Ribbed Scarf</span><span class="text-sm font-bold text-tcar02-acc">$54</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-3/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Leather ankle boots" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Ankle Boots</span><span class="text-sm font-bold text-tcar02-acc">$189</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-4/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Canvas crossbody bag" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Crossbody Bag</span><span class="text-sm font-bold text-tcar02-acc">$96</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-5/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Round tortoiseshell sunglasses" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Sunglasses</span><span class="text-sm font-bold text-tcar02-acc">$72</span></div>
</li>
</ul>
</div>
</section>@import "tailwindcss";
@theme {
--color-tcar02-bg: #faf7f5;
--color-tcar02-bg: oklch(0.98 0.005 50);
--color-tcar02-edge: #eee3dd;
--color-tcar02-edge: oklch(0.93 0.01 45);
--color-tcar02-ph: #efe6e0;
--color-tcar02-ph: oklch(0.92 0.012 45);
--color-tcar02-track: #d9cfc9;
--color-tcar02-track: oklch(0.85 0.015 45);
--color-tcar02-ink: #2a211d;
--color-tcar02-ink: oklch(0.26 0.015 45);
--color-tcar02-acc: #a8442c;
--color-tcar02-acc: oklch(0.55 0.14 25);
--font-tcar02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-02 {
width: 100%;
min-height: 100svh;
}
.tcar-02 ::selection {
background: var(--color-tcar02-acc);
color: #fff;
}
/* Reduced motion also calms the snap scroll itself, which no variant reaches. */
@media (prefers-reduced-motion: reduce) {
.tcar-02 ul {
scroll-behavior: auto;
}
}@import "tailwindcss";
@theme {
--color-tcar02-bg: #faf7f5;
--color-tcar02-bg: oklch(0.98 0.005 50);
--color-tcar02-edge: #eee3dd;
--color-tcar02-edge: oklch(0.93 0.01 45);
--color-tcar02-ph: #efe6e0;
--color-tcar02-ph: oklch(0.92 0.012 45);
--color-tcar02-track: #d9cfc9;
--color-tcar02-track: oklch(0.85 0.015 45);
--color-tcar02-ink: #2a211d;
--color-tcar02-ink: oklch(0.26 0.015 45);
--color-tcar02-acc: #a8442c;
--color-tcar02-acc: oklch(0.55 0.14 25);
--font-tcar02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-02 {
width: 100%;
min-height: 100svh;
}
.tcar-02 ::selection {
background: var(--color-tcar02-acc);
color: #fff;
}
/* Reduced motion also calms the snap scroll itself, which no variant reaches. */
@media (prefers-reduced-motion: reduce) {
.tcar-02 ul {
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-tcar02-bg: #faf7f5;
--color-tcar02-bg: oklch(0.98 0.005 50);
--color-tcar02-edge: #eee3dd;
--color-tcar02-edge: oklch(0.93 0.01 45);
--color-tcar02-ph: #efe6e0;
--color-tcar02-ph: oklch(0.92 0.012 45);
--color-tcar02-track: #d9cfc9;
--color-tcar02-track: oklch(0.85 0.015 45);
--color-tcar02-ink: #2a211d;
--color-tcar02-ink: oklch(0.26 0.015 45);
--color-tcar02-acc: #a8442c;
--color-tcar02-acc: oklch(0.55 0.14 25);
--font-tcar02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-02 {
width: 100%;
min-height: 100svh;
}
.tcar-02 ::selection {
background: var(--color-tcar02-acc);
color: #fff;
}
/* Reduced motion also calms the snap scroll itself, which no variant reaches. */
@media (prefers-reduced-motion: reduce) {
.tcar-02 ul {
scroll-behavior: auto;
}
}@import "tailwindcss";
@theme {
--color-tcar02-bg: #faf7f5;
--color-tcar02-bg: oklch(0.98 0.005 50);
--color-tcar02-edge: #eee3dd;
--color-tcar02-edge: oklch(0.93 0.01 45);
--color-tcar02-ph: #efe6e0;
--color-tcar02-ph: oklch(0.92 0.012 45);
--color-tcar02-track: #d9cfc9;
--color-tcar02-track: oklch(0.85 0.015 45);
--color-tcar02-ink: #2a211d;
--color-tcar02-ink: oklch(0.26 0.015 45);
--color-tcar02-acc: #a8442c;
--color-tcar02-acc: oklch(0.55 0.14 25);
--font-tcar02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-02 {
width: 100%;
min-height: 100svh;
}
.tcar-02 ::selection {
background: var(--color-tcar02-acc);
color: #fff;
}
/* Reduced motion also calms the snap scroll itself, which no variant reaches. */
@media (prefers-reduced-motion: reduce) {
.tcar-02 ul {
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;800&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;800&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- This is the port that shrinks:
snap-x snap-mandatoryandsnap-startare real utilities, so onlyscroll-padding-leftand the scrollbar pair need arbitrary syntax. - The
@media (min-width:560px)card-width override becomessm:basis-[...]on the card. Tailwind'ssmis 640px rather than 560px; if the exact original breakpoint matters, mint--breakpoint-tcar02: 35remin@themeand usetcar02:basis-[...]. - UI change from the CSS original: the card hover now animates
translateandbox-shadowexplicitly rather than the shorthandtransform, andmotion-reduce:hover:translate-y-0keeps the shadow cue for users who opted out of motion — the original simply removed the transition and kept the jump.
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 Shop the Look Multi-Item Card Slider with Scroll Snap
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-shop-the-look-card-slider-scroll-snap/
A horizontal product-card rail: three to four cards on desktop, one-per-view on mobile — the 'complete the look' pattern. Tailwind ships first-class snap-x snap-mandatory / snap-start utilities, so this is the rare carousel where the port is shorter than the original, not just better located.
## HTML
```html
<section class="tcar-02 w-full min-h-svh grid place-items-center bg-tcar02-bg font-tcar02-sans px-3 py-10" aria-label="Shop the look product rail">
<div class="w-[min(760px,100%)]">
<h3 class="text-[15px] font-bold tracking-[0.02em] text-tcar02-ink mx-2 mb-3.5">Complete the look</h3>
<ul tabindex="0" role="group" aria-label="Recommended products, scrollable" class="list-none flex gap-4 overflow-x-auto px-2 pt-1.5 pb-4 m-0 snap-x snap-mandatory [scroll-padding-left:8px] [scrollbar-width:thin] [scrollbar-color:var(--color-tcar02-track)_transparent] focus-visible:outline-3 focus-visible:outline-tcar02-acc focus-visible:outline-offset-2 focus-visible:rounded-xl">
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-1/500/600" width="500" height="600" decoding="async" alt="Oversized wool coat" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Wool Overcoat</span><span class="text-sm font-bold text-tcar02-acc">$248</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-2/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Ribbed knit scarf" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Ribbed Scarf</span><span class="text-sm font-bold text-tcar02-acc">$54</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-3/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Leather ankle boots" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Ankle Boots</span><span class="text-sm font-bold text-tcar02-acc">$189</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-4/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Canvas crossbody bag" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Crossbody Bag</span><span class="text-sm font-bold text-tcar02-acc">$96</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-5/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Round tortoiseshell sunglasses" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Sunglasses</span><span class="text-sm font-bold text-tcar02-acc">$72</span></div>
</li>
</ul>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar02-bg: #faf7f5;
--color-tcar02-bg: oklch(0.98 0.005 50);
--color-tcar02-edge: #eee3dd;
--color-tcar02-edge: oklch(0.93 0.01 45);
--color-tcar02-ph: #efe6e0;
--color-tcar02-ph: oklch(0.92 0.012 45);
--color-tcar02-track: #d9cfc9;
--color-tcar02-track: oklch(0.85 0.015 45);
--color-tcar02-ink: #2a211d;
--color-tcar02-ink: oklch(0.26 0.015 45);
--color-tcar02-acc: #a8442c;
--color-tcar02-acc: oklch(0.55 0.14 25);
--font-tcar02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-02 {
width: 100%;
min-height: 100svh;
}
.tcar-02 ::selection {
background: var(--color-tcar02-acc);
color: #fff;
}
/* Reduced motion also calms the snap scroll itself, which no variant reaches. */
@media (prefers-reduced-motion: reduce) {
.tcar-02 ul {
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 Shop the Look Multi-Item Card Slider with Scroll Snap
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-shop-the-look-card-slider-scroll-snap/
A horizontal product-card rail: three to four cards on desktop, one-per-view on mobile — the 'complete the look' pattern. Tailwind ships first-class snap-x snap-mandatory / snap-start utilities, so this is the rare carousel where the port is shorter than the original, not just better located.
## HTML
```html
<section class="tcar-02 w-full min-h-svh grid place-items-center bg-tcar02-bg font-tcar02-sans px-3 py-10" aria-label="Shop the look product rail">
<div class="w-[min(760px,100%)]">
<h3 class="text-[15px] font-bold tracking-[0.02em] text-tcar02-ink mx-2 mb-3.5">Complete the look</h3>
<ul tabindex="0" role="group" aria-label="Recommended products, scrollable" class="list-none flex gap-4 overflow-x-auto px-2 pt-1.5 pb-4 m-0 snap-x snap-mandatory [scroll-padding-left:8px] [scrollbar-width:thin] [scrollbar-color:var(--color-tcar02-track)_transparent] focus-visible:outline-3 focus-visible:outline-tcar02-acc focus-visible:outline-offset-2 focus-visible:rounded-xl">
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-1/500/600" width="500" height="600" decoding="async" alt="Oversized wool coat" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Wool Overcoat</span><span class="text-sm font-bold text-tcar02-acc">$248</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-2/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Ribbed knit scarf" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Ribbed Scarf</span><span class="text-sm font-bold text-tcar02-acc">$54</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-3/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Leather ankle boots" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Ankle Boots</span><span class="text-sm font-bold text-tcar02-acc">$189</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-4/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Canvas crossbody bag" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Crossbody Bag</span><span class="text-sm font-bold text-tcar02-acc">$96</span></div>
</li>
<li class="flex-none basis-[clamp(200px,70%,236px)] sm:basis-[calc((100%-32px)/3)] snap-start bg-white border border-tcar02-edge rounded-2xl overflow-hidden shadow-[0_12px_30px_-26px_oklch(0.35_0.06_40/0.7)] transition-[translate,box-shadow] duration-250 hover:-translate-y-1 hover:shadow-[0_18px_36px_-24px_oklch(0.35_0.06_40/0.6)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div class="aspect-[5/6] bg-tcar02-ph"><img src="https://picsum.photos/seed/look-5/500/600" width="500" height="600" loading="lazy" decoding="async" alt="Round tortoiseshell sunglasses" class="size-full object-cover block"></div>
<div class="flex items-center justify-between gap-2.5 px-3.5 pt-3 pb-3.5"><span class="text-sm font-semibold text-tcar02-ink">Sunglasses</span><span class="text-sm font-bold text-tcar02-acc">$72</span></div>
</li>
</ul>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar02-bg: #faf7f5;
--color-tcar02-bg: oklch(0.98 0.005 50);
--color-tcar02-edge: #eee3dd;
--color-tcar02-edge: oklch(0.93 0.01 45);
--color-tcar02-ph: #efe6e0;
--color-tcar02-ph: oklch(0.92 0.012 45);
--color-tcar02-track: #d9cfc9;
--color-tcar02-track: oklch(0.85 0.015 45);
--color-tcar02-ink: #2a211d;
--color-tcar02-ink: oklch(0.26 0.015 45);
--color-tcar02-acc: #a8442c;
--color-tcar02-acc: oklch(0.55 0.14 25);
--font-tcar02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-02 {
width: 100%;
min-height: 100svh;
}
.tcar-02 ::selection {
background: var(--color-tcar02-acc);
color: #fff;
}
/* Reduced motion also calms the snap scroll itself, which no variant reaches. */
@media (prefers-reduced-motion: reduce) {
.tcar-02 ul {
scroll-behavior: auto;
}
}
```How this works
Snap is a first-class utility. snap-x snap-mandatory on the container and snap-start on the items is the whole mechanism; the browser snaps the nearest card edge to the leading edge as you scroll and nothing measures anything.
The breakpoint moves into the class list. The CSS version puts the three-up layout in a @media (min-width:560px) block far from the card. sm:basis-[calc((100%-32px)/3)] states it on the card, so one glance answers "how wide is this at every size".
The rail is a focus target. tabindex="0" plus role="group" and a label make it reachable, and focus-visible:outline-3 proves it — arrow keys then scroll it natively.
Make it yours
- Two-up instead of three:
sm:basis-[calc((100%-16px)/2)]. - Looser feel: swap
snap-mandatoryforsnap-proximity. - Edge breathing room: the rail's
gap-4and[scroll-padding-left:8px]. - Retheme the price and focus ring through
--color-tcar02-acc.
Gotchas — read before shipping
snap-startbelongs on the items, not the container. On the container it silently no-ops and the rail free-scrolls.- Don't reach for
[scrollbar-width:none]on desktop — a rail with no visible scrollbar and no arrows gives mouse users nothing to grab. - Each card image needs
aspect-[5/6]; lazy-loaded product shots without a reserved box are the most common CLS source on a PDP.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
CSS scroll-snap is Baseline and universally supported; the floor quoted is Tailwind v4's generated sheet. scrollbar-color falls back to the platform scrollbar in older Safari.