10 / 15
All 15 in 15 Tailwind Card Grid Layouts
- 01Tailwind Stats Dashboard KPI Grid
- 02Tailwind Hero Photo Collage Grid
- 03Tailwind Pricing Comparison Card Grid
- 04Tailwind Testimonial Wall Grid
- 05Tailwind Editorial Tabloid Bento Layout
- 06Tailwind Featured Article Magazine Grid
- 07Tailwind Asymmetric Bento Box Feature Grid
- 08Tailwind Stratified Bento Grid Layout
- 09Tailwind Equal-Height Product Grid
- 10Tailwind Fluid Masonry Card Grid
- 11Tailwind Auto-Fit Blog Archive Grid
- 12Tailwind Team Directory Face Grid
- 13Tailwind 3D Hover Flip Card Grid
- 14Tailwind Use-Case Showcase Card Grid
- 15Tailwind Glass Bento Grid Layout
Tailwind Fluid Masonry Card Grid
A Pinterest-style wall built on multi-column flow, which is still the only masonry that works everywhere. Tailwind has first-class utilities for the whole technique — columns-3, break-inside-avoid, gap-4 — so this is one of the few demos where the port is shorter than the CSS and nothing has to stay in the stylesheet.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tcg-04 w-full min-h-svh bg-tcg04-bg font-tcg04-sans px-6 py-12" aria-label="Fluid masonry card grid demo">
<div class="max-w-[900px] mx-auto columns-3 max-[640px]:columns-2 gap-4">
<figure style="--h:280px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fbcfe8,#a855f7] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Portrait Study</figcaption>
</figure>
<figure style="--h:180px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#bae6fd,#0284c7] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Harbor Light</figcaption>
</figure>
<figure style="--h:340px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fde68a,#d97706] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Desert Bloom</figcaption>
</figure>
<figure style="--h:220px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#bbf7d0,#15803d] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Quiet Forest</figcaption>
</figure>
<figure style="--h:300px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fecaca,#b91c1c] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Red Canyon</figcaption>
</figure>
<figure style="--h:200px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#ddd6fe,#6d28d9] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Twilight Field</figcaption>
</figure>
</div>
</section><section class="tcg-04 w-full min-h-svh bg-tcg04-bg font-tcg04-sans px-6 py-12" aria-label="Fluid masonry card grid demo">
<div class="max-w-[900px] mx-auto columns-3 max-[640px]:columns-2 gap-4">
<figure style="--h:280px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fbcfe8,#a855f7] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Portrait Study</figcaption>
</figure>
<figure style="--h:180px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#bae6fd,#0284c7] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Harbor Light</figcaption>
</figure>
<figure style="--h:340px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fde68a,#d97706] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Desert Bloom</figcaption>
</figure>
<figure style="--h:220px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#bbf7d0,#15803d] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Quiet Forest</figcaption>
</figure>
<figure style="--h:300px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fecaca,#b91c1c] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Red Canyon</figcaption>
</figure>
<figure style="--h:200px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#ddd6fe,#6d28d9] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Twilight Field</figcaption>
</figure>
</div>
</section>@import "tailwindcss";
@theme {
--color-tcg04-bg: #111114;
--color-tcg04-bg: oklch(0.17 0.004 285);
--color-tcg04-card: #1a1a1f;
--color-tcg04-card: oklch(0.22 0.006 285);
--font-tcg04-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract. */
.tcg-04 {
width: 100%;
min-height: 100svh;
}
.tcg-04 ::selection {
background: #a855f7;
color: #fff;
}@import "tailwindcss";
@theme {
--color-tcg04-bg: #111114;
--color-tcg04-bg: oklch(0.17 0.004 285);
--color-tcg04-card: #1a1a1f;
--color-tcg04-card: oklch(0.22 0.006 285);
--font-tcg04-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract. */
.tcg-04 {
width: 100%;
min-height: 100svh;
}
.tcg-04 ::selection {
background: #a855f7;
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-tcg04-bg: #111114;
--color-tcg04-bg: oklch(0.17 0.004 285);
--color-tcg04-card: #1a1a1f;
--color-tcg04-card: oklch(0.22 0.006 285);
--font-tcg04-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract. */
.tcg-04 {
width: 100%;
min-height: 100svh;
}
.tcg-04 ::selection {
background: #a855f7;
color: #fff;
}@import "tailwindcss";
@theme {
--color-tcg04-bg: #111114;
--color-tcg04-bg: oklch(0.17 0.004 285);
--color-tcg04-card: #1a1a1f;
--color-tcg04-card: oklch(0.22 0.006 285);
--font-tcg04-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract. */
.tcg-04 {
width: 100%;
min-height: 100svh;
}
.tcg-04 ::selection {
background: #a855f7;
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.
- Tailwind ships utilities for the entire multicol technique, so this stylesheet holds nothing but tokens, the root rule and a selection colour. It is the shortest CSS field in the collection.
break-inside-avoidis a real utility, not an arbitrary property, which is worth noting: the one rule that makes multicol masonry work is a first-class citizen.- The per-card
--his a placeholder for real image intrinsic height and disappears entirely once you drop in<img>elements — the demo is honest about being a stand-in. - The image zoom moved from a descendant hover rule to
group-hover:, so the card and the thing that reacts to hovering it are one class list apart. - Captions are legible at rest (
opacity-85) rather than hover-only, because a caption that only exists on hover does not exist on a touch device. - The single media query becomes
max-[640px]:columns-2— one utility, on the container it governs.
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 Fluid Masonry Card Grid
Source: https://codefronts.com/layouts/tailwind-card-grid-layout/tailwind-fluid-masonry-card-grid/
A Pinterest-style wall built on multi-column flow, which is still the only masonry that works everywhere. Tailwind has first-class utilities for the whole technique — columns-3, break-inside-avoid, gap-4 — so this is one of the few demos where the port is shorter than the CSS and nothing has to stay in the stylesheet.
## HTML
```html
<section class="tcg-04 w-full min-h-svh bg-tcg04-bg font-tcg04-sans px-6 py-12" aria-label="Fluid masonry card grid demo">
<div class="max-w-[900px] mx-auto columns-3 max-[640px]:columns-2 gap-4">
<figure style="--h:280px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fbcfe8,#a855f7] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Portrait Study</figcaption>
</figure>
<figure style="--h:180px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#bae6fd,#0284c7] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Harbor Light</figcaption>
</figure>
<figure style="--h:340px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fde68a,#d97706] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Desert Bloom</figcaption>
</figure>
<figure style="--h:220px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#bbf7d0,#15803d] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Quiet Forest</figcaption>
</figure>
<figure style="--h:300px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fecaca,#b91c1c] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Red Canyon</figcaption>
</figure>
<figure style="--h:200px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#ddd6fe,#6d28d9] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Twilight Field</figcaption>
</figure>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcg04-bg: #111114;
--color-tcg04-bg: oklch(0.17 0.004 285);
--color-tcg04-card: #1a1a1f;
--color-tcg04-card: oklch(0.22 0.006 285);
--font-tcg04-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract. */
.tcg-04 {
width: 100%;
min-height: 100svh;
}
.tcg-04 ::selection {
background: #a855f7;
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 Fluid Masonry Card Grid
Source: https://codefronts.com/layouts/tailwind-card-grid-layout/tailwind-fluid-masonry-card-grid/
A Pinterest-style wall built on multi-column flow, which is still the only masonry that works everywhere. Tailwind has first-class utilities for the whole technique — columns-3, break-inside-avoid, gap-4 — so this is one of the few demos where the port is shorter than the CSS and nothing has to stay in the stylesheet.
## HTML
```html
<section class="tcg-04 w-full min-h-svh bg-tcg04-bg font-tcg04-sans px-6 py-12" aria-label="Fluid masonry card grid demo">
<div class="max-w-[900px] mx-auto columns-3 max-[640px]:columns-2 gap-4">
<figure style="--h:280px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fbcfe8,#a855f7] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Portrait Study</figcaption>
</figure>
<figure style="--h:180px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#bae6fd,#0284c7] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Harbor Light</figcaption>
</figure>
<figure style="--h:340px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fde68a,#d97706] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Desert Bloom</figcaption>
</figure>
<figure style="--h:220px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#bbf7d0,#15803d] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Quiet Forest</figcaption>
</figure>
<figure style="--h:300px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#fecaca,#b91c1c] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Red Canyon</figcaption>
</figure>
<figure style="--h:200px" class="group relative inline-block w-full mb-4 break-inside-avoid rounded-xl overflow-hidden bg-tcg04-card">
<div class="w-full h-[var(--h)] bg-linear-[160deg,#ddd6fe,#6d28d9] transition-transform duration-400 group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100" aria-hidden="true"></div>
<figcaption class="absolute inset-x-0 bottom-0 px-3 py-2.5 text-[.78rem] font-semibold text-white bg-linear-[0deg,oklch(0_0_0/0.6),transparent] opacity-85 transition-opacity duration-250 group-hover:opacity-100 motion-reduce:transition-none">Twilight Field</figcaption>
</figure>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcg04-bg: #111114;
--color-tcg04-bg: oklch(0.17 0.004 285);
--color-tcg04-card: #1a1a1f;
--color-tcg04-card: oklch(0.22 0.006 285);
--font-tcg04-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract. */
.tcg-04 {
width: 100%;
min-height: 100svh;
}
.tcg-04 ::selection {
background: #a855f7;
color: #fff;
}
```How this works
Multicol, not grid. columns-3 plus gap-4 gives three balanced columns; each card is inline-block w-full mb-4 break-inside-avoid so it fills its column's width and never splits. Because columns fill independently, a tall card and a short card sit flush with no leftover gap — the masonry look, from two utilities.
The gutter is two numbers that must agree. gap-4 sets the column gap and mb-4 sets the vertical rhythm. Tailwind's shared spacing scale makes that agreement legible; in CSS they were a column-gap and a margin-bottom in different rules.
Heights stay inline. Each card's --h stands in for a real photo's intrinsic height. It is per-instance data, so it belongs in style and is read back with h-[var(--h)] — with real <img> elements you delete both and let the images size themselves.
Hover zoom without layout cost. overflow-hidden on the card and group-hover:scale-105 on the inner div; the transform runs on the compositor and the column balance never recalculates.
Make it yours
- Swap
columns-3forcolumns-[240px]and the browser picks the column count for you — responsive with no breakpoint at all. - Hide captions until hover with
opacity-0 group-hover:opacity-100 group-focus-within:opacity-100. - Change the gutters by editing
gap-*and the cards'mb-*together; keeping them equal is what makes the wall read as a grid. - Replace the placeholder divs with
<img class="w-full h-auto">and delete the inline--h. - Add a slight tilt on hover with
group-hover:rotate-1for a scrapbook feel.
Gotchas — read before shipping
- Multicol orders items top-to-bottom per column, not left-to-right. Visual order and DOM order diverge, so keep the source order meaningful for screen readers and keyboard tabbing.
- Dropping
break-inside-avoidlets a card split across a column boundary, which looks like a rendering bug rather than a layout choice. columns-*and CSS Grid do not compose: you cannot span a multicol child across columns the way a grid item spans tracks. If you need a featured tile, use grid and accept ragged bottoms.- Native
grid-template-rows: masonryis still not interoperable; multicol is the shippable answer in 2026 and this demo is deliberately built on it. - Per-card heights must be inline custom properties, not generated class names — the compiler only sees static class strings.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
CSS multi-column and break-inside have universal support and run far further back than the floor quoted, which is Tailwind v4's own generated sheet.