21 / 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 Zoom-on-Hover Image Gallery Slider
A scroll-snap rail where hovering any tile scales the photograph up inside its fixed frame. The frame clips the overflow, so the picture grows and the layout does not move — the most reusable three-utility idea in the collection.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tcar-21 w-full min-h-svh grid place-items-center bg-tcar21-bg font-tcar21-sans px-3 py-10" aria-label="Dish gallery">
<ul tabindex="0" role="group" aria-label="Dishes, scrollable" class="list-none flex gap-4 w-[min(760px,100%)] overflow-x-auto p-3 m-0 snap-x snap-mandatory [scroll-padding:12px] [scrollbar-width:thin] [scrollbar-color:var(--color-tcar21-track)_transparent] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-2 focus-visible:rounded-2xl">
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-1/600/600" width="600" height="600" decoding="async" alt="Ramen bowl" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Tonkotsu Ramen</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-2/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Stack of pancakes" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Buttermilk Stack</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-3/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Poke bowl" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Ahi Poke Bowl</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-4/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Berry tart" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Berry Tart</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-5/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Espresso" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Double Espresso</span>
</a>
</li>
</ul>
</section><section class="tcar-21 w-full min-h-svh grid place-items-center bg-tcar21-bg font-tcar21-sans px-3 py-10" aria-label="Dish gallery">
<ul tabindex="0" role="group" aria-label="Dishes, scrollable" class="list-none flex gap-4 w-[min(760px,100%)] overflow-x-auto p-3 m-0 snap-x snap-mandatory [scroll-padding:12px] [scrollbar-width:thin] [scrollbar-color:var(--color-tcar21-track)_transparent] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-2 focus-visible:rounded-2xl">
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-1/600/600" width="600" height="600" decoding="async" alt="Ramen bowl" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Tonkotsu Ramen</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-2/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Stack of pancakes" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Buttermilk Stack</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-3/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Poke bowl" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Ahi Poke Bowl</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-4/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Berry tart" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Berry Tart</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-5/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Espresso" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Double Espresso</span>
</a>
</li>
</ul>
</section>@import "tailwindcss";
@theme {
--color-tcar21-bg: #fbf5f2;
--color-tcar21-bg: oklch(0.97 0.008 30);
--color-tcar21-ph: #eeddd7;
--color-tcar21-ph: oklch(0.91 0.02 30);
--color-tcar21-track: #e6cdc6;
--color-tcar21-track: oklch(0.87 0.03 30);
--color-tcar21-acc: #c3113c;
--color-tcar21-acc: oklch(0.52 0.2 15);
--font-tcar21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-21 {
width: 100%;
min-height: 100svh;
}
.tcar-21 ::selection {
background: var(--color-tcar21-acc);
color: #fff;
}
@media (prefers-reduced-motion: reduce) {
.tcar-21 ul {
scroll-behavior: auto;
}
}@import "tailwindcss";
@theme {
--color-tcar21-bg: #fbf5f2;
--color-tcar21-bg: oklch(0.97 0.008 30);
--color-tcar21-ph: #eeddd7;
--color-tcar21-ph: oklch(0.91 0.02 30);
--color-tcar21-track: #e6cdc6;
--color-tcar21-track: oklch(0.87 0.03 30);
--color-tcar21-acc: #c3113c;
--color-tcar21-acc: oklch(0.52 0.2 15);
--font-tcar21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-21 {
width: 100%;
min-height: 100svh;
}
.tcar-21 ::selection {
background: var(--color-tcar21-acc);
color: #fff;
}
@media (prefers-reduced-motion: reduce) {
.tcar-21 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-tcar21-bg: #fbf5f2;
--color-tcar21-bg: oklch(0.97 0.008 30);
--color-tcar21-ph: #eeddd7;
--color-tcar21-ph: oklch(0.91 0.02 30);
--color-tcar21-track: #e6cdc6;
--color-tcar21-track: oklch(0.87 0.03 30);
--color-tcar21-acc: #c3113c;
--color-tcar21-acc: oklch(0.52 0.2 15);
--font-tcar21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-21 {
width: 100%;
min-height: 100svh;
}
.tcar-21 ::selection {
background: var(--color-tcar21-acc);
color: #fff;
}
@media (prefers-reduced-motion: reduce) {
.tcar-21 ul {
scroll-behavior: auto;
}
}@import "tailwindcss";
@theme {
--color-tcar21-bg: #fbf5f2;
--color-tcar21-bg: oklch(0.97 0.008 30);
--color-tcar21-ph: #eeddd7;
--color-tcar21-ph: oklch(0.91 0.02 30);
--color-tcar21-track: #e6cdc6;
--color-tcar21-track: oklch(0.87 0.03 30);
--color-tcar21-acc: #c3113c;
--color-tcar21-acc: oklch(0.52 0.2 15);
--font-tcar21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-21 {
width: 100%;
min-height: 100svh;
}
.tcar-21 ::selection {
background: var(--color-tcar21-acc);
color: #fff;
}
@media (prefers-reduced-motion: reduce) {
.tcar-21 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&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.
- Three utilities carry the whole idea:
overflow-hiddenon the parent,group-hover:scale-*on the child, and a transition. It is the pattern from this collection most worth lifting into other components wholesale. transition-[scale]rather thantransition-transform: with v4's individual transform properties, naming the one property that changes keeps the caption'stranslatetransition independent.- UI change from the CSS original: the caption is now pinned visible under
motion-reduce:instead of merely losing its transition, and the accent darkened from#e11d48tooklch(0.52 0.2 15)so the focus ring clears 3:1 against the warm background.
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 Zoom-on-Hover Image Gallery Slider
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-zoom-on-hover-image-gallery-slider/
A scroll-snap rail where hovering any tile scales the photograph up inside its fixed frame. The frame clips the overflow, so the picture grows and the layout does not move — the most reusable three-utility idea in the collection.
## HTML
```html
<section class="tcar-21 w-full min-h-svh grid place-items-center bg-tcar21-bg font-tcar21-sans px-3 py-10" aria-label="Dish gallery">
<ul tabindex="0" role="group" aria-label="Dishes, scrollable" class="list-none flex gap-4 w-[min(760px,100%)] overflow-x-auto p-3 m-0 snap-x snap-mandatory [scroll-padding:12px] [scrollbar-width:thin] [scrollbar-color:var(--color-tcar21-track)_transparent] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-2 focus-visible:rounded-2xl">
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-1/600/600" width="600" height="600" decoding="async" alt="Ramen bowl" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Tonkotsu Ramen</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-2/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Stack of pancakes" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Buttermilk Stack</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-3/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Poke bowl" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Ahi Poke Bowl</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-4/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Berry tart" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Berry Tart</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-5/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Espresso" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Double Espresso</span>
</a>
</li>
</ul>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar21-bg: #fbf5f2;
--color-tcar21-bg: oklch(0.97 0.008 30);
--color-tcar21-ph: #eeddd7;
--color-tcar21-ph: oklch(0.91 0.02 30);
--color-tcar21-track: #e6cdc6;
--color-tcar21-track: oklch(0.87 0.03 30);
--color-tcar21-acc: #c3113c;
--color-tcar21-acc: oklch(0.52 0.2 15);
--font-tcar21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-21 {
width: 100%;
min-height: 100svh;
}
.tcar-21 ::selection {
background: var(--color-tcar21-acc);
color: #fff;
}
@media (prefers-reduced-motion: reduce) {
.tcar-21 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 Zoom-on-Hover Image Gallery Slider
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-zoom-on-hover-image-gallery-slider/
A scroll-snap rail where hovering any tile scales the photograph up inside its fixed frame. The frame clips the overflow, so the picture grows and the layout does not move — the most reusable three-utility idea in the collection.
## HTML
```html
<section class="tcar-21 w-full min-h-svh grid place-items-center bg-tcar21-bg font-tcar21-sans px-3 py-10" aria-label="Dish gallery">
<ul tabindex="0" role="group" aria-label="Dishes, scrollable" class="list-none flex gap-4 w-[min(760px,100%)] overflow-x-auto p-3 m-0 snap-x snap-mandatory [scroll-padding:12px] [scrollbar-width:thin] [scrollbar-color:var(--color-tcar21-track)_transparent] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-2 focus-visible:rounded-2xl">
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-1/600/600" width="600" height="600" decoding="async" alt="Ramen bowl" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Tonkotsu Ramen</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-2/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Stack of pancakes" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Buttermilk Stack</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-3/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Poke bowl" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Ahi Poke Bowl</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-4/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Berry tart" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Berry Tart</span>
</a>
</li>
<li class="flex-none basis-[clamp(180px,60%,220px)] snap-start">
<a href="#" class="group relative block aspect-square rounded-2xl overflow-hidden no-underline bg-tcar21-ph shadow-[0_14px_30px_-22px_oklch(0.4_0.15_10/0.6)] focus-visible:outline-3 focus-visible:outline-tcar21-acc focus-visible:outline-offset-[3px]">
<img src="https://picsum.photos/seed/zoom-5/600/600" width="600" height="600" loading="lazy" decoding="async" alt="Espresso" class="size-full object-cover block transition-[scale] duration-[550ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] group-hover:scale-[1.18] group-focus-within:scale-[1.18] motion-reduce:transition-none motion-reduce:group-hover:scale-100">
<span class="absolute inset-x-0 bottom-0 px-3.5 pt-8 pb-3 text-white text-sm font-bold bg-[linear-gradient(transparent,oklch(0.22_0.08_10/0.88))] opacity-0 translate-y-1.5 transition-[opacity,translate] duration-350 group-hover:opacity-100 group-hover:translate-y-0 group-focus-within:opacity-100 group-focus-within:translate-y-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:translate-y-0">Double Espresso</span>
</a>
</li>
</ul>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar21-bg: #fbf5f2;
--color-tcar21-bg: oklch(0.97 0.008 30);
--color-tcar21-ph: #eeddd7;
--color-tcar21-ph: oklch(0.91 0.02 30);
--color-tcar21-track: #e6cdc6;
--color-tcar21-track: oklch(0.87 0.03 30);
--color-tcar21-acc: #c3113c;
--color-tcar21-acc: oklch(0.52 0.2 15);
--font-tcar21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.tcar-21 {
width: 100%;
min-height: 100svh;
}
.tcar-21 ::selection {
background: var(--color-tcar21-acc);
color: #fff;
}
@media (prefers-reduced-motion: reduce) {
.tcar-21 ul {
scroll-behavior: auto;
}
}
```How this works
Scale the image, clip the frame. The snap box keeps its exact size because nothing about it changes; only its child grows, and overflow-hidden crops the excess. The rail's geometry is therefore constant, which is what makes the effect feel solid rather than bouncy.
One group, two effects. The link is the group; the image zooms and the caption rises from it.
Reduced motion keeps the caption. motion-reduce: removes the zoom and the slide but pins the caption visible, because it carries the dish name.
Make it yours
- Zoom strength:
group-hover:scale-[1.18]. - Tile shape:
aspect-squareand thebasis-*clamp. - Colour pop: add
group-hover:saturate-150alongside the scale. - Caption on or off, per tile.
Gotchas — read before shipping
overflow-hiddengoes on the frame, not the rail. On the rail it would clip the scroll area itself.- Scale the
<img>, never the tile — scaling the tile changes the snap geometry and the rail jitters as you hover along it. group-focus-within:alongsidegroup-hover:, or the caption is mouse-only.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
scroll-snap and transforms are universally supported; the floor quoted is Tailwind v4's generated sheet.