13 / 22
All 22 in 22 Tailwind CSS Image Gallery
- 01Tailwind Hexagon Honeycomb Image Gallery with clip-path
- 02Tailwind Justified Image Gallery with Aspect-Ratio Flex Rows
- 03Tailwind Expanding Panel Image Gallery with Flex-Grow Transitions
- 04Tailwind :has() Hover Spotlight Image Grid
- 05Tailwind Radial Orbit Image Gallery with Counter-Rotating Thumbnails
- 06Tailwind Interactive Pointer Trail Image Gallery
- 07Tailwind Masonry Image Gallery with CSS Columns (No JavaScript)
- 08Tailwind Metro Tile Grid Gallery with Dense Auto-Flow
- 09Tailwind Editorial Magazine Grid Gallery with Blend-Mode Headline
- 10Tailwind Pure CSS Lightbox Gallery with :target (No JavaScript)
- 11Tailwind Filmstrip Carousel Gallery with CSS Scroll-Snap
- 12Tailwind Accordion Image Gallery with Flex-Grow on Hover & Focus
- 13Tailwind Mosaic Grid Gallery with Contained Zoom on Hover
- 14Tailwind Glassmorphism Image Cards with backdrop-blur
- 15Tailwind Diagonal Slice Reveal Gallery with clip-path Halves
- 16Tailwind 3D Tilt Parallax Image Cards with Pointer-Driven Variables
- 17Tailwind 3D Cube Image Viewer with Radio-Driven Rotation
- 18Tailwind 3D Perspective Depth Stack Gallery That Fans on Focus
- 19Tailwind Infinite Scrolling Image Marquee with Seamless Loop
- 20Tailwind Ken Burns Slideshow Gallery with Staggered Cross-Fade
- 21Tailwind Polaroid Photo Stack Gallery with Rotate-on-Hover
- 22Tailwind Scattered Photo Collage with :target Spotlight
Tailwind Mosaic Grid Gallery with Contained Zoom on Hover
A crisp mosaic where hovering a tile zooms the photograph cleanly inside its frame: the image scales, the tile does not, so nothing overlaps its neighbours and nothing reflows. The catalog micro-interaction, done the performant way.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tgl-13 w-full min-h-svh grid place-items-center bg-tgl13-bg font-tgl13-sans px-5 py-10" aria-label="Mosaic zoom gallery">
<div class="w-[min(820px,100%)] grid grid-cols-4 gap-2.5 auto-rows-[1fr] [grid-auto-flow:dense] max-[600px]:grid-cols-2">
<figure class="group relative m-0 col-span-2 row-span-2 [aspect-ratio:auto] overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1451187580459-43490279c0fa?q=80&w=800&h=800&auto=format&fit=crop" alt="Golden hour over rolling hills" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Hills</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?q=80&w=400&h=400&auto=format&fit=crop" alt="Macro of a flower" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Bloom</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1519125323398-675f0ddb6308?q=80&w=400&h=400&auto=format&fit=crop" alt="Wild deer in a field" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Wildlife</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1478720568477-152d9b164e26?q=80&w=400&h=400&auto=format&fit=crop" alt="Backlit green leaf" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Detail</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1566073771259-6a8506099945?q=80&w=400&h=400&auto=format&fit=crop" alt="Forest waterfall" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Falls</figcaption>
</figure>
<figure class="group relative m-0 col-span-2 [aspect-ratio:auto] overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1509440159596-0249088772ff?q=80&w=800&h=400&auto=format&fit=crop" alt="Valley panorama" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Valley</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1589003077984-894e133dabab?q=80&w=400&h=400&auto=format&fit=crop" alt="Dramatic cloudscape" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Sky</figcaption>
</figure>
</div>
</section><section class="tgl-13 w-full min-h-svh grid place-items-center bg-tgl13-bg font-tgl13-sans px-5 py-10" aria-label="Mosaic zoom gallery">
<div class="w-[min(820px,100%)] grid grid-cols-4 gap-2.5 auto-rows-[1fr] [grid-auto-flow:dense] max-[600px]:grid-cols-2">
<figure class="group relative m-0 col-span-2 row-span-2 [aspect-ratio:auto] overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1451187580459-43490279c0fa?q=80&w=800&h=800&auto=format&fit=crop" alt="Golden hour over rolling hills" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Hills</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?q=80&w=400&h=400&auto=format&fit=crop" alt="Macro of a flower" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Bloom</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1519125323398-675f0ddb6308?q=80&w=400&h=400&auto=format&fit=crop" alt="Wild deer in a field" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Wildlife</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1478720568477-152d9b164e26?q=80&w=400&h=400&auto=format&fit=crop" alt="Backlit green leaf" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Detail</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1566073771259-6a8506099945?q=80&w=400&h=400&auto=format&fit=crop" alt="Forest waterfall" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Falls</figcaption>
</figure>
<figure class="group relative m-0 col-span-2 [aspect-ratio:auto] overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1509440159596-0249088772ff?q=80&w=800&h=400&auto=format&fit=crop" alt="Valley panorama" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Valley</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1589003077984-894e133dabab?q=80&w=400&h=400&auto=format&fit=crop" alt="Dramatic cloudscape" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Sky</figcaption>
</figure>
</div>
</section>@import "tailwindcss";
@theme {
--color-tgl13-bg: #f2f4f1;
--color-tgl13-bg: oklch(0.96 0.006 145);
--color-tgl13-well: #dfe4de;
--color-tgl13-well: oklch(0.91 0.008 145);
--color-tgl13-acc: #2f8a5a;
--color-tgl13-acc: oklch(0.56 0.13 155);
--font-tgl13-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tgl-13 {
width: 100%;
min-height: 100svh;
}
.tgl-13 ::selection {
background: var(--color-tgl13-acc);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tgl13-bg: #f2f4f1;
--color-tgl13-bg: oklch(0.96 0.006 145);
--color-tgl13-well: #dfe4de;
--color-tgl13-well: oklch(0.91 0.008 145);
--color-tgl13-acc: #2f8a5a;
--color-tgl13-acc: oklch(0.56 0.13 155);
--font-tgl13-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tgl-13 {
width: 100%;
min-height: 100svh;
}
.tgl-13 ::selection {
background: var(--color-tgl13-acc);
color: #fff;
}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-tgl13-bg: #f2f4f1;
--color-tgl13-bg: oklch(0.96 0.006 145);
--color-tgl13-well: #dfe4de;
--color-tgl13-well: oklch(0.91 0.008 145);
--color-tgl13-acc: #2f8a5a;
--color-tgl13-acc: oklch(0.56 0.13 155);
--font-tgl13-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tgl-13 {
width: 100%;
min-height: 100svh;
}
.tgl-13 ::selection {
background: var(--color-tgl13-acc);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tgl13-bg: #f2f4f1;
--color-tgl13-bg: oklch(0.96 0.006 145);
--color-tgl13-well: #dfe4de;
--color-tgl13-well: oklch(0.91 0.008 145);
--color-tgl13-acc: #2f8a5a;
--color-tgl13-acc: oklch(0.56 0.13 155);
--font-tgl13-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tgl-13 {
width: 100%;
min-height: 100svh;
}
.tgl-13 ::selection {
background: var(--color-tgl13-acc);
color: #fff;
}<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=Space+Grotesk: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=Space+Grotesk:wght@400;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The clearest demonstration in the collection of what
groupbuys: one state on the tile, two independent reveals on two children, and no descendant selector anywhere. transition-transformrather thantransition-allis deliberate. On a grid item,allwould put the grid's own resolved sizes in the transition list.- UI change from the CSS original: captions now stay hidden until hover on touch as well, but every tile keeps a real
<figcaption>in the DOM, so the label is available to assistive tech at all times rather than being a hover-only string.
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 Mosaic Grid Gallery with Contained Zoom on Hover
Source: https://codefronts.com/snippets/tailwind-css-image-gallery/tailwind-mosaic-grid-gallery-contained-zoom/
A crisp mosaic where hovering a tile zooms the photograph cleanly inside its frame: the image scales, the tile does not, so nothing overlaps its neighbours and nothing reflows. The catalog micro-interaction, done the performant way.
## HTML
```html
<section class="tgl-13 w-full min-h-svh grid place-items-center bg-tgl13-bg font-tgl13-sans px-5 py-10" aria-label="Mosaic zoom gallery">
<div class="w-[min(820px,100%)] grid grid-cols-4 gap-2.5 auto-rows-[1fr] [grid-auto-flow:dense] max-[600px]:grid-cols-2">
<figure class="group relative m-0 col-span-2 row-span-2 [aspect-ratio:auto] overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1451187580459-43490279c0fa?q=80&w=800&h=800&auto=format&fit=crop" alt="Golden hour over rolling hills" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Hills</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?q=80&w=400&h=400&auto=format&fit=crop" alt="Macro of a flower" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Bloom</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1519125323398-675f0ddb6308?q=80&w=400&h=400&auto=format&fit=crop" alt="Wild deer in a field" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Wildlife</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1478720568477-152d9b164e26?q=80&w=400&h=400&auto=format&fit=crop" alt="Backlit green leaf" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Detail</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1566073771259-6a8506099945?q=80&w=400&h=400&auto=format&fit=crop" alt="Forest waterfall" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Falls</figcaption>
</figure>
<figure class="group relative m-0 col-span-2 [aspect-ratio:auto] overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1509440159596-0249088772ff?q=80&w=800&h=400&auto=format&fit=crop" alt="Valley panorama" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Valley</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1589003077984-894e133dabab?q=80&w=400&h=400&auto=format&fit=crop" alt="Dramatic cloudscape" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Sky</figcaption>
</figure>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgl13-bg: #f2f4f1;
--color-tgl13-bg: oklch(0.96 0.006 145);
--color-tgl13-well: #dfe4de;
--color-tgl13-well: oklch(0.91 0.008 145);
--color-tgl13-acc: #2f8a5a;
--color-tgl13-acc: oklch(0.56 0.13 155);
--font-tgl13-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tgl-13 {
width: 100%;
min-height: 100svh;
}
.tgl-13 ::selection {
background: var(--color-tgl13-acc);
color: #fff;
}
```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 Mosaic Grid Gallery with Contained Zoom on Hover
Source: https://codefronts.com/snippets/tailwind-css-image-gallery/tailwind-mosaic-grid-gallery-contained-zoom/
A crisp mosaic where hovering a tile zooms the photograph cleanly inside its frame: the image scales, the tile does not, so nothing overlaps its neighbours and nothing reflows. The catalog micro-interaction, done the performant way.
## HTML
```html
<section class="tgl-13 w-full min-h-svh grid place-items-center bg-tgl13-bg font-tgl13-sans px-5 py-10" aria-label="Mosaic zoom gallery">
<div class="w-[min(820px,100%)] grid grid-cols-4 gap-2.5 auto-rows-[1fr] [grid-auto-flow:dense] max-[600px]:grid-cols-2">
<figure class="group relative m-0 col-span-2 row-span-2 [aspect-ratio:auto] overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1451187580459-43490279c0fa?q=80&w=800&h=800&auto=format&fit=crop" alt="Golden hour over rolling hills" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Hills</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?q=80&w=400&h=400&auto=format&fit=crop" alt="Macro of a flower" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Bloom</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1519125323398-675f0ddb6308?q=80&w=400&h=400&auto=format&fit=crop" alt="Wild deer in a field" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Wildlife</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1478720568477-152d9b164e26?q=80&w=400&h=400&auto=format&fit=crop" alt="Backlit green leaf" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Detail</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1566073771259-6a8506099945?q=80&w=400&h=400&auto=format&fit=crop" alt="Forest waterfall" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Falls</figcaption>
</figure>
<figure class="group relative m-0 col-span-2 [aspect-ratio:auto] overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1509440159596-0249088772ff?q=80&w=800&h=400&auto=format&fit=crop" alt="Valley panorama" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Valley</figcaption>
</figure>
<figure class="group relative m-0 aspect-square overflow-hidden rounded-[10px] bg-tgl13-well">
<img src="https://images.unsplash.com/photo-1589003077984-894e133dabab?q=80&w=400&h=400&auto=format&fit=crop" alt="Dramatic cloudscape" loading="lazy" decoding="async" class="absolute inset-0 w-full h-full object-cover transition-transform duration-[550ms] ease-[cubic-bezier(0.2,0.7,0.2,1)] group-hover:scale-[1.16] group-focus-within:scale-[1.16] motion-reduce:transition-none">
<figcaption class="absolute inset-x-0 bottom-0 px-3 pt-5 pb-2.5 text-white text-xs font-semibold tracking-[0.04em] bg-[linear-gradient(0deg,rgba(8,20,12,0.8),transparent)] opacity-0 transition-opacity duration-[350ms] group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none">Sky</figcaption>
</figure>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgl13-bg: #f2f4f1;
--color-tgl13-bg: oklch(0.96 0.006 145);
--color-tgl13-well: #dfe4de;
--color-tgl13-well: oklch(0.91 0.008 145);
--color-tgl13-acc: #2f8a5a;
--color-tgl13-acc: oklch(0.56 0.13 155);
--font-tgl13-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tgl-13 {
width: 100%;
min-height: 100svh;
}
.tgl-13 ::selection {
background: var(--color-tgl13-acc);
color: #fff;
}
```How this works
Scale the image, never the tile. Scaling the tile would push its neighbours and reflow the grid on every hover; scaling the image inside an overflow-hidden frame stays entirely on the compositor. Tailwind makes the division explicit, because the two utilities are on two different elements and you cannot confuse them.
The caption is a second group consumer. One group on the tile drives both the zoom and the scrim caption's fade, so adding a third reveal is one more group-hover: utility, never a new selector.
Feature tiles are declarative. col-span-2 row-span-2 with [aspect-ratio:auto]; every other tile stays aspect-square and the mosaic never loses its grid.
Make it yours
- Zoom depth:
group-hover:scale-[1.16]— 1.08 is restrained, 1.25 is punchy. - Focal point: add
origin-[60%_30%]to zoom toward the subject rather than the centre. - Promote or demote any tile by adding or deleting its span utilities.
Gotchas — read before shipping
- Without
overflow-hiddenon the tile the zoomed image spills over its neighbours — the clip is what makes the effect contained. - Keep
aspect-squareon standard tiles so mixed source ratios cannot break the mosaic alignment. - Do not transition
all: nametransition-transformso the grid's own layout properties are never animated by accident.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Grid, transforms and overflow clipping are universal; the floor is Tailwind v4's generated sheet.