12 / 30
All 30 in 30 Tailwind CSS Grid Layouts
- 01Tailwind Full-Bleed Article Layout for Long-Form Editorial
- 02Tailwind Docs Layout with Sticky Table of Contents
- 03Tailwind Photo Gallery Grid with auto-fill and Real Images
- 04Tailwind Holy Grail Page Layout for a News Site
- 05Tailwind Data Table with Subgrid Rows and Status Pills
- 06Tailwind Overlapping Card Hero for a Case Study
- 07Tailwind Help Center Layout with Fixed Sidebars
- 08Tailwind 12 Column Grid System for Marketing Pages
- 09Tailwind Bento Grid for a Product Feature Section
- 10Tailwind Magazine Spread Layout with Overlapping Headline
- 11Tailwind Responsive Card Grid for an Integrations Directory
- 12Tailwind CMS Category Grid that Compacts Itself with has()
- 13Tailwind Masonry Layout for a Saved Ideas Board
- 14Tailwind Hexagon Team Grid with clip-path Avatars
- 15Tailwind Subgrid Cards with Perfectly Aligned Buttons
- 16Tailwind Analytics Dashboard Layout with Grid App Shell
- 17Tailwind Pricing Table with Subgrid and a Featured Plan
- 18Tailwind Kanban Board with Scroll Snap Columns
- 19Tailwind Video Thumbnail Grid with Zero Layout Shift
- 20Tailwind Container Query Card for Reusable Article Teasers
- 21Tailwind Diagonal Section Band with skewY Counter-Skew
- 22Tailwind Asymmetric Poster Hero with Layered Grid Regions
- 23Tailwind Mosaic Photo Wall with a Designed Span Sequence
- 24Tailwind Dense Grid Packing for a Mixed-Size Asset Library
- 25Tailwind Onboarding Stepper with CSS Counters
- 26Tailwind macOS Window Layout with Vibrancy Sidebar
- 27Tailwind Scroll Snap Carousel with Peeking Slides
- 28Tailwind Status Map UI with Grid Coordinate Pins
- 29Tailwind Logo Wall with 1px Gap Hairline Dividers
- 30Tailwind Periodic Table Layout with Grid Coordinates
Tailwind CMS Category Grid that Compacts Itself with has()
A blog's topic index that re-designs itself by count: three topics render as feature cards with descriptions and post counts; add a fifth and the same list compacts into a chip wall. One class list, no JavaScript, no editor training.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tgx-12 w-full min-h-svh bg-tgx12-coal font-tgx12-sans p-6 flex flex-col gap-4">
<header class="flex flex-col gap-1">
<p class="font-tgx12-mono text-[0.66rem] tracking-[0.16em] uppercase text-tgx12-amber">Fieldnotes · Topics</p>
<h2 class="text-[1.3rem] font-semibold text-white tracking-[-0.01em]">Browse by topic</h2>
</header>
<div class="flex flex-col gap-2">
<p class="text-[0.75rem] text-tgx12-dim">Featured collections <span class="text-tgx12-amber">· 3 items → roomy cards</span></p>
<ul class="list-none grid gap-3 grid-cols-[repeat(auto-fit,minmax(min(220px,100%),1fr))] *:flex *:flex-col *:gap-1.5 *:rounded-xl *:border *:border-tgx12-edge *:bg-tgx12-card *:p-4 has-[>*:nth-child(5)]:gap-2 has-[>*:nth-child(5)]:grid-cols-[repeat(auto-fit,minmax(min(116px,100%),1fr))] has-[>*:nth-child(5)]:*:p-2.5 has-[>*:nth-child(5)]:*:items-center has-[>*:nth-child(5)]:*:text-center has-[>*:nth-child(5)]:*:justify-center">
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Layout</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Grid, subgrid and the geometry of a page.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">24 posts</span></li>
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Typography</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Measure, rhythm and the case against 16px everywhere.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">18 posts</span></li>
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Performance</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Shipping less, measuring honestly.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">31 posts</span></li>
</ul>
</div>
<div class="flex flex-col gap-2">
<p class="text-[0.75rem] text-tgx12-dim">All topics <span class="text-tgx12-amber">· 8 items → the same list compacts</span></p>
<ul class="list-none grid gap-3 grid-cols-[repeat(auto-fit,minmax(min(220px,100%),1fr))] *:flex *:flex-col *:gap-1.5 *:rounded-xl *:border *:border-tgx12-edge *:bg-tgx12-card *:p-4 has-[>*:nth-child(5)]:gap-2 has-[>*:nth-child(5)]:grid-cols-[repeat(auto-fit,minmax(min(116px,100%),1fr))] has-[>*:nth-child(5)]:*:p-2.5 has-[>*:nth-child(5)]:*:items-center has-[>*:nth-child(5)]:*:text-center has-[>*:nth-child(5)]:*:justify-center">
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Layout</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">24</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Typography</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">18</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Performance</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">31</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Accessibility</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">22</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Tooling</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">14</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Colour</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">9</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Motion</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">11</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Process</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">7</span></li>
</ul>
</div>
</section><section class="tgx-12 w-full min-h-svh bg-tgx12-coal font-tgx12-sans p-6 flex flex-col gap-4">
<header class="flex flex-col gap-1">
<p class="font-tgx12-mono text-[0.66rem] tracking-[0.16em] uppercase text-tgx12-amber">Fieldnotes · Topics</p>
<h2 class="text-[1.3rem] font-semibold text-white tracking-[-0.01em]">Browse by topic</h2>
</header>
<div class="flex flex-col gap-2">
<p class="text-[0.75rem] text-tgx12-dim">Featured collections <span class="text-tgx12-amber">· 3 items → roomy cards</span></p>
<ul class="list-none grid gap-3 grid-cols-[repeat(auto-fit,minmax(min(220px,100%),1fr))] *:flex *:flex-col *:gap-1.5 *:rounded-xl *:border *:border-tgx12-edge *:bg-tgx12-card *:p-4 has-[>*:nth-child(5)]:gap-2 has-[>*:nth-child(5)]:grid-cols-[repeat(auto-fit,minmax(min(116px,100%),1fr))] has-[>*:nth-child(5)]:*:p-2.5 has-[>*:nth-child(5)]:*:items-center has-[>*:nth-child(5)]:*:text-center has-[>*:nth-child(5)]:*:justify-center">
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Layout</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Grid, subgrid and the geometry of a page.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">24 posts</span></li>
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Typography</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Measure, rhythm and the case against 16px everywhere.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">18 posts</span></li>
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Performance</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Shipping less, measuring honestly.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">31 posts</span></li>
</ul>
</div>
<div class="flex flex-col gap-2">
<p class="text-[0.75rem] text-tgx12-dim">All topics <span class="text-tgx12-amber">· 8 items → the same list compacts</span></p>
<ul class="list-none grid gap-3 grid-cols-[repeat(auto-fit,minmax(min(220px,100%),1fr))] *:flex *:flex-col *:gap-1.5 *:rounded-xl *:border *:border-tgx12-edge *:bg-tgx12-card *:p-4 has-[>*:nth-child(5)]:gap-2 has-[>*:nth-child(5)]:grid-cols-[repeat(auto-fit,minmax(min(116px,100%),1fr))] has-[>*:nth-child(5)]:*:p-2.5 has-[>*:nth-child(5)]:*:items-center has-[>*:nth-child(5)]:*:text-center has-[>*:nth-child(5)]:*:justify-center">
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Layout</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">24</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Typography</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">18</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Performance</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">31</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Accessibility</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">22</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Tooling</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">14</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Colour</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">9</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Motion</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">11</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Process</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">7</span></li>
</ul>
</div>
</section>@import "tailwindcss";
@theme {
--color-tgx12-coal: #211d16;
--color-tgx12-coal: oklch(0.21 0.012 75);
--color-tgx12-card: #2b261d;
--color-tgx12-card: oklch(0.26 0.015 75);
--color-tgx12-edge: #4a4130;
--color-tgx12-edge: oklch(0.38 0.03 75);
--color-tgx12-amber: #f0c46a;
--color-tgx12-amber: oklch(0.83 0.13 80);
--color-tgx12-dim: #c2b8a5;
--color-tgx12-dim: oklch(0.8 0.02 80);
--color-tgx12-faint: #9a9081;
--color-tgx12-faint: oklch(0.67 0.02 80);
--font-tgx12-sans: 'Inter Tight', system-ui, sans-serif;
--font-tgx12-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tgx-12 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tgx12-coal: #211d16;
--color-tgx12-coal: oklch(0.21 0.012 75);
--color-tgx12-card: #2b261d;
--color-tgx12-card: oklch(0.26 0.015 75);
--color-tgx12-edge: #4a4130;
--color-tgx12-edge: oklch(0.38 0.03 75);
--color-tgx12-amber: #f0c46a;
--color-tgx12-amber: oklch(0.83 0.13 80);
--color-tgx12-dim: #c2b8a5;
--color-tgx12-dim: oklch(0.8 0.02 80);
--color-tgx12-faint: #9a9081;
--color-tgx12-faint: oklch(0.67 0.02 80);
--font-tgx12-sans: 'Inter Tight', system-ui, sans-serif;
--font-tgx12-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tgx-12 {
width: 100%;
min-height: 100svh;
}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-tgx12-coal: #211d16;
--color-tgx12-coal: oklch(0.21 0.012 75);
--color-tgx12-card: #2b261d;
--color-tgx12-card: oklch(0.26 0.015 75);
--color-tgx12-edge: #4a4130;
--color-tgx12-edge: oklch(0.38 0.03 75);
--color-tgx12-amber: #f0c46a;
--color-tgx12-amber: oklch(0.83 0.13 80);
--color-tgx12-dim: #c2b8a5;
--color-tgx12-dim: oklch(0.8 0.02 80);
--color-tgx12-faint: #9a9081;
--color-tgx12-faint: oklch(0.67 0.02 80);
--font-tgx12-sans: 'Inter Tight', system-ui, sans-serif;
--font-tgx12-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tgx-12 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tgx12-coal: #211d16;
--color-tgx12-coal: oklch(0.21 0.012 75);
--color-tgx12-card: #2b261d;
--color-tgx12-card: oklch(0.26 0.015 75);
--color-tgx12-edge: #4a4130;
--color-tgx12-edge: oklch(0.38 0.03 75);
--color-tgx12-amber: #f0c46a;
--color-tgx12-amber: oklch(0.83 0.13 80);
--color-tgx12-dim: #c2b8a5;
--color-tgx12-dim: oklch(0.8 0.02 80);
--color-tgx12-faint: #9a9081;
--color-tgx12-faint: oklch(0.67 0.02 80);
--font-tgx12-sans: 'Inter Tight', system-ui, sans-serif;
--font-tgx12-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tgx-12 {
width: 100%;
min-height: 100svh;
}<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=Inter+Tight:wght@400;500;600&family=JetBrains+Mono:wght@400;500&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=Inter+Tight:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Both lists ship the identical class list — copy one onto the other and the only difference is how many
<li>children it has. That is the demo. - Post counts survive both states because they are just another child; the compact state centres them under the label instead of hiding them.
- Product upgrade: 'Design / Engineering / Research' placeholders became a real topic index with descriptions and post counts, and the two states are labelled by what triggers them rather than by the selector that implements them.
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 CMS Category Grid that Compacts Itself with has()
Source: https://codefronts.com/layouts/tailwind-css-grid-layouts/tailwind-cms-category-grid-compacts-has/
A blog's topic index that re-designs itself by count: three topics render as feature cards with descriptions and post counts; add a fifth and the same list compacts into a chip wall. One class list, no JavaScript, no editor training.
## HTML
```html
<section class="tgx-12 w-full min-h-svh bg-tgx12-coal font-tgx12-sans p-6 flex flex-col gap-4">
<header class="flex flex-col gap-1">
<p class="font-tgx12-mono text-[0.66rem] tracking-[0.16em] uppercase text-tgx12-amber">Fieldnotes · Topics</p>
<h2 class="text-[1.3rem] font-semibold text-white tracking-[-0.01em]">Browse by topic</h2>
</header>
<div class="flex flex-col gap-2">
<p class="text-[0.75rem] text-tgx12-dim">Featured collections <span class="text-tgx12-amber">· 3 items → roomy cards</span></p>
<ul class="list-none grid gap-3 grid-cols-[repeat(auto-fit,minmax(min(220px,100%),1fr))] *:flex *:flex-col *:gap-1.5 *:rounded-xl *:border *:border-tgx12-edge *:bg-tgx12-card *:p-4 has-[>*:nth-child(5)]:gap-2 has-[>*:nth-child(5)]:grid-cols-[repeat(auto-fit,minmax(min(116px,100%),1fr))] has-[>*:nth-child(5)]:*:p-2.5 has-[>*:nth-child(5)]:*:items-center has-[>*:nth-child(5)]:*:text-center has-[>*:nth-child(5)]:*:justify-center">
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Layout</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Grid, subgrid and the geometry of a page.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">24 posts</span></li>
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Typography</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Measure, rhythm and the case against 16px everywhere.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">18 posts</span></li>
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Performance</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Shipping less, measuring honestly.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">31 posts</span></li>
</ul>
</div>
<div class="flex flex-col gap-2">
<p class="text-[0.75rem] text-tgx12-dim">All topics <span class="text-tgx12-amber">· 8 items → the same list compacts</span></p>
<ul class="list-none grid gap-3 grid-cols-[repeat(auto-fit,minmax(min(220px,100%),1fr))] *:flex *:flex-col *:gap-1.5 *:rounded-xl *:border *:border-tgx12-edge *:bg-tgx12-card *:p-4 has-[>*:nth-child(5)]:gap-2 has-[>*:nth-child(5)]:grid-cols-[repeat(auto-fit,minmax(min(116px,100%),1fr))] has-[>*:nth-child(5)]:*:p-2.5 has-[>*:nth-child(5)]:*:items-center has-[>*:nth-child(5)]:*:text-center has-[>*:nth-child(5)]:*:justify-center">
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Layout</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">24</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Typography</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">18</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Performance</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">31</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Accessibility</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">22</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Tooling</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">14</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Colour</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">9</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Motion</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">11</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Process</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">7</span></li>
</ul>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgx12-coal: #211d16;
--color-tgx12-coal: oklch(0.21 0.012 75);
--color-tgx12-card: #2b261d;
--color-tgx12-card: oklch(0.26 0.015 75);
--color-tgx12-edge: #4a4130;
--color-tgx12-edge: oklch(0.38 0.03 75);
--color-tgx12-amber: #f0c46a;
--color-tgx12-amber: oklch(0.83 0.13 80);
--color-tgx12-dim: #c2b8a5;
--color-tgx12-dim: oklch(0.8 0.02 80);
--color-tgx12-faint: #9a9081;
--color-tgx12-faint: oklch(0.67 0.02 80);
--font-tgx12-sans: 'Inter Tight', system-ui, sans-serif;
--font-tgx12-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tgx-12 {
width: 100%;
min-height: 100svh;
}
```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 CMS Category Grid that Compacts Itself with has()
Source: https://codefronts.com/layouts/tailwind-css-grid-layouts/tailwind-cms-category-grid-compacts-has/
A blog's topic index that re-designs itself by count: three topics render as feature cards with descriptions and post counts; add a fifth and the same list compacts into a chip wall. One class list, no JavaScript, no editor training.
## HTML
```html
<section class="tgx-12 w-full min-h-svh bg-tgx12-coal font-tgx12-sans p-6 flex flex-col gap-4">
<header class="flex flex-col gap-1">
<p class="font-tgx12-mono text-[0.66rem] tracking-[0.16em] uppercase text-tgx12-amber">Fieldnotes · Topics</p>
<h2 class="text-[1.3rem] font-semibold text-white tracking-[-0.01em]">Browse by topic</h2>
</header>
<div class="flex flex-col gap-2">
<p class="text-[0.75rem] text-tgx12-dim">Featured collections <span class="text-tgx12-amber">· 3 items → roomy cards</span></p>
<ul class="list-none grid gap-3 grid-cols-[repeat(auto-fit,minmax(min(220px,100%),1fr))] *:flex *:flex-col *:gap-1.5 *:rounded-xl *:border *:border-tgx12-edge *:bg-tgx12-card *:p-4 has-[>*:nth-child(5)]:gap-2 has-[>*:nth-child(5)]:grid-cols-[repeat(auto-fit,minmax(min(116px,100%),1fr))] has-[>*:nth-child(5)]:*:p-2.5 has-[>*:nth-child(5)]:*:items-center has-[>*:nth-child(5)]:*:text-center has-[>*:nth-child(5)]:*:justify-center">
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Layout</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Grid, subgrid and the geometry of a page.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">24 posts</span></li>
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Typography</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Measure, rhythm and the case against 16px everywhere.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">18 posts</span></li>
<li><strong class="text-[0.95rem] font-semibold text-tgx12-amber">Performance</strong><span class="text-[0.78rem] leading-[1.5] text-tgx12-dim">Shipping less, measuring honestly.</span><span class="mt-1 text-[0.7rem] tabular-nums text-tgx12-faint">31 posts</span></li>
</ul>
</div>
<div class="flex flex-col gap-2">
<p class="text-[0.75rem] text-tgx12-dim">All topics <span class="text-tgx12-amber">· 8 items → the same list compacts</span></p>
<ul class="list-none grid gap-3 grid-cols-[repeat(auto-fit,minmax(min(220px,100%),1fr))] *:flex *:flex-col *:gap-1.5 *:rounded-xl *:border *:border-tgx12-edge *:bg-tgx12-card *:p-4 has-[>*:nth-child(5)]:gap-2 has-[>*:nth-child(5)]:grid-cols-[repeat(auto-fit,minmax(min(116px,100%),1fr))] has-[>*:nth-child(5)]:*:p-2.5 has-[>*:nth-child(5)]:*:items-center has-[>*:nth-child(5)]:*:text-center has-[>*:nth-child(5)]:*:justify-center">
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Layout</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">24</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Typography</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">18</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Performance</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">31</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Accessibility</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">22</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Tooling</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">14</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Colour</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">9</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Motion</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">11</span></li>
<li><strong class="text-[0.8rem] font-semibold text-tgx12-amber">Process</strong><span class="text-[0.68rem] tabular-nums text-tgx12-faint">7</span></li>
</ul>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgx12-coal: #211d16;
--color-tgx12-coal: oklch(0.21 0.012 75);
--color-tgx12-card: #2b261d;
--color-tgx12-card: oklch(0.26 0.015 75);
--color-tgx12-edge: #4a4130;
--color-tgx12-edge: oklch(0.38 0.03 75);
--color-tgx12-amber: #f0c46a;
--color-tgx12-amber: oklch(0.83 0.13 80);
--color-tgx12-dim: #c2b8a5;
--color-tgx12-dim: oklch(0.8 0.02 80);
--color-tgx12-faint: #9a9081;
--color-tgx12-faint: oklch(0.67 0.02 80);
--font-tgx12-sans: 'Inter Tight', system-ui, sans-serif;
--font-tgx12-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tgx-12 {
width: 100%;
min-height: 100svh;
}
```How this works
The gate is a count. :has(> :nth-child(5)) is true only when a fifth child exists; everything downstream follows. An editor adding topics never files a layout ticket.
The cost is repetition. In CSS one rule flipped three custom properties; in Tailwind each flipped property needs its own gated variant. For a two-state component that is a fair trade — and the trade is worth naming out loud.
Make it yours
- Move the threshold by changing the index:
has-[>*:nth-child(7)]:. - Three density tiers: stack two gates (roomy → medium → compact).
- The gate can flip anything — radius, colour, even
content-visibility.
Gotchas — read before shipping
- Count DIRECT children with
>; without it a single card with five paragraphs triggers the compact state. :has()invalidates ancestor styles on DOM change — fine at this size, not for thousand-node trees.- Design both states deliberately; auto-compacting into an unconsidered layout is worse than not compacting.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 117+ | 16+ | 113+ | 117+ |
Floor set by oklch(), subgrid as this demo is written. The core technique itself goes back further — Chrome 111+.
:has() is Baseline since Dec 2023; without it the grid stays roomy, which is a usable fallback.