30 Tailwind CSS Grid Layouts
20 / 30

All 30 in 30 Tailwind CSS Grid Layouts

  1. 01Tailwind Full-Bleed Article Layout for Long-Form Editorial
  2. 02Tailwind Docs Layout with Sticky Table of Contents
  3. 03Tailwind Photo Gallery Grid with auto-fill and Real Images
  4. 04Tailwind Holy Grail Page Layout for a News Site
  5. 05Tailwind Data Table with Subgrid Rows and Status Pills
  6. 06Tailwind Overlapping Card Hero for a Case Study
  7. 07Tailwind Help Center Layout with Fixed Sidebars
  8. 08Tailwind 12 Column Grid System for Marketing Pages
  9. 09Tailwind Bento Grid for a Product Feature Section
  10. 10Tailwind Magazine Spread Layout with Overlapping Headline
  11. 11Tailwind Responsive Card Grid for an Integrations Directory
  12. 12Tailwind CMS Category Grid that Compacts Itself with has()
  13. 13Tailwind Masonry Layout for a Saved Ideas Board
  14. 14Tailwind Hexagon Team Grid with clip-path Avatars
  15. 15Tailwind Subgrid Cards with Perfectly Aligned Buttons
  16. 16Tailwind Analytics Dashboard Layout with Grid App Shell
  17. 17Tailwind Pricing Table with Subgrid and a Featured Plan
  18. 18Tailwind Kanban Board with Scroll Snap Columns
  19. 19Tailwind Video Thumbnail Grid with Zero Layout Shift
  20. 20Tailwind Container Query Card for Reusable Article Teasers
  21. 21Tailwind Diagonal Section Band with skewY Counter-Skew
  22. 22Tailwind Asymmetric Poster Hero with Layered Grid Regions
  23. 23Tailwind Mosaic Photo Wall with a Designed Span Sequence
  24. 24Tailwind Dense Grid Packing for a Mixed-Size Asset Library
  25. 25Tailwind Onboarding Stepper with CSS Counters
  26. 26Tailwind macOS Window Layout with Vibrancy Sidebar
  27. 27Tailwind Scroll Snap Carousel with Peeking Slides
  28. 28Tailwind Status Map UI with Grid Coordinate Pins
  29. 29Tailwind Logo Wall with 1px Gap Hairline Dividers
  30. 30Tailwind Periodic Table Layout with Grid Coordinates
Pure TailwindMIT licensed

Tailwind Container Query Card for Reusable Article Teasers

One article teaser, two layouts — decided by the card's own width. Dropped in the main column it goes horizontal with a wide photo; the identical markup in the sidebar stacks. In v4 the container query is core syntax.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="tgx-20 w-full min-h-svh bg-tgx20-bg font-tgx20-sans p-6">
  <div class="grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)] max-md:grid-cols-[minmax(0,1fr)] gap-5">
    <main class="flex flex-col gap-2.5">
      <p class="font-tgx20-mono text-[0.66rem] text-tgx20-mut">main · wide container → horizontal</p>
      <div class="@container/card">
        <article class="grid [grid-template-areas:'media'_'body'] @md/card:[grid-template-areas:'media_body'] @md/card:grid-cols-[150px_minmax(0,1fr)] rounded-2xl overflow-hidden bg-white border border-tgx20-edge shadow-[0_12px_28px_-22px_oklch(0.45_0.05_45/0.9)]">
          <div class="[grid-area:media] relative min-h-[130px] @md/card:min-h-full bg-tgx20-cell">
            <img src="https://images.unsplash.com/photo-1447752875215-b2761acb3c5d?w=500&h=500&q=80&auto=format&fit=crop" alt="Trail winding through coastal pine woodland" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
          </div>
          <div class="[grid-area:body] p-4 flex flex-col gap-2">
            <p class="text-[0.64rem] font-semibold tracking-[0.14em] uppercase text-tgx20-link">Trail guide</p>
            <h3 class="text-[clamp(0.92rem,4.5cqi,1.2rem)] font-semibold text-tgx20-ink leading-[1.25]">The coast path, in three days</h3>
            <p class="text-[0.8rem] leading-[1.55] text-tgx20-mut">Same markup, same stylesheet. The card asked its container — not the viewport — how much room it has, and chose the horizontal arrangement.</p>
            <a href="#0" class="mt-auto inline-flex items-center gap-1 min-h-11 text-[0.8rem] font-semibold text-tgx20-link no-underline hover:underline underline-offset-4 focus-visible:outline-2 focus-visible:outline-tgx20-link focus-visible:outline-offset-2 rounded">Read guide <span aria-hidden="true">→</span></a>
          </div>
        </article>
      </div>
    </main>
    <aside class="flex flex-col gap-2.5">
      <p class="font-tgx20-mono text-[0.66rem] text-tgx20-mut">aside · narrow → stacked</p>
      <div class="@container/card">
        <article class="grid [grid-template-areas:'media'_'body'] @md/card:[grid-template-areas:'media_body'] @md/card:grid-cols-[150px_minmax(0,1fr)] rounded-2xl overflow-hidden bg-white border border-tgx20-edge shadow-[0_12px_28px_-22px_oklch(0.45_0.05_45/0.9)]">
          <div class="[grid-area:media] relative min-h-[130px] @md/card:min-h-full bg-tgx20-cell">
            <img src="https://images.unsplash.com/photo-1447752875215-b2761acb3c5d?w=500&h=500&q=80&auto=format&fit=crop" alt="Trail winding through coastal pine woodland" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
          </div>
          <div class="[grid-area:body] p-4 flex flex-col gap-2">
            <p class="text-[0.64rem] font-semibold tracking-[0.14em] uppercase text-tgx20-link">Trail guide</p>
            <h3 class="text-[clamp(0.92rem,4.5cqi,1.2rem)] font-semibold text-tgx20-ink leading-[1.25]">The coast path, in three days</h3>
            <p class="text-[0.8rem] leading-[1.55] text-tgx20-mut">Identical component, adapted by its container.</p>
            <a href="#0" class="mt-auto inline-flex items-center gap-1 min-h-11 text-[0.8rem] font-semibold text-tgx20-link no-underline hover:underline underline-offset-4 focus-visible:outline-2 focus-visible:outline-tgx20-link focus-visible:outline-offset-2 rounded">Read guide <span aria-hidden="true">→</span></a>
          </div>
        </article>
      </div>
    </aside>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tgx20-bg: #faf4ee;
  --color-tgx20-bg: oklch(0.965 0.012 60);
  --color-tgx20-cell: #eadfd3;
  --color-tgx20-cell: oklch(0.9 0.02 60);
  --color-tgx20-edge: #e7cdb6;
  --color-tgx20-edge: oklch(0.87 0.05 60);
  --color-tgx20-ink: #3a2a1e;
  --color-tgx20-ink: oklch(0.3 0.04 45);
  --color-tgx20-mut: #6b5648;
  --color-tgx20-mut: oklch(0.47 0.03 45);
  --color-tgx20-link: #a1481f;
  --color-tgx20-link: oklch(0.52 0.15 40);
  --font-tgx20-sans: 'Inter Tight', system-ui, sans-serif;
  --font-tgx20-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tgx-20 {
  width: 100%;
  min-height: 100svh;
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<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.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-tgx20-bg: #faf4ee;
  --color-tgx20-bg: oklch(0.965 0.012 60);
  --color-tgx20-cell: #eadfd3;
  --color-tgx20-cell: oklch(0.9 0.02 60);
  --color-tgx20-edge: #e7cdb6;
  --color-tgx20-edge: oklch(0.87 0.05 60);
  --color-tgx20-ink: #3a2a1e;
  --color-tgx20-ink: oklch(0.3 0.04 45);
  --color-tgx20-mut: #6b5648;
  --color-tgx20-mut: oklch(0.47 0.03 45);
  --color-tgx20-link: #a1481f;
  --color-tgx20-link: oklch(0.52 0.15 40);
  --font-tgx20-sans: 'Inter Tight', system-ui, sans-serif;
  --font-tgx20-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tgx-20 {
  width: 100%;
  min-height: 100svh;
}
3Fonts used by this demooptional — skip if you have your own type stack
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://images.unsplash.com">
<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.

  • With a real photograph the two layouts read as two genuinely different cards, which is the entire selling point of container queries — and impossible to feel with a gradient block.
  • The cqi title sizing is visible here: the same heading is a step smaller in the sidebar without a single breakpoint.
  • Product upgrade: the card became a real article teaser with a kicker, a photo and a CTA — and this remains the only demo in the collection whose stylesheet is nothing but tokens.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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 Container Query Card for Reusable Article Teasers
Source: https://codefronts.com/layouts/tailwind-css-grid-layouts/tailwind-container-query-card-article-teasers/

One article teaser, two layouts — decided by the card's own width. Dropped in the main column it goes horizontal with a wide photo; the identical markup in the sidebar stacks. In v4 the container query is core syntax.
## HTML
```html
<section class="tgx-20 w-full min-h-svh bg-tgx20-bg font-tgx20-sans p-6">
  <div class="grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)] max-md:grid-cols-[minmax(0,1fr)] gap-5">
    <main class="flex flex-col gap-2.5">
      <p class="font-tgx20-mono text-[0.66rem] text-tgx20-mut">main · wide container → horizontal</p>
      <div class="@container/card">
        <article class="grid [grid-template-areas:'media'_'body'] @md/card:[grid-template-areas:'media_body'] @md/card:grid-cols-[150px_minmax(0,1fr)] rounded-2xl overflow-hidden bg-white border border-tgx20-edge shadow-[0_12px_28px_-22px_oklch(0.45_0.05_45/0.9)]">
          <div class="[grid-area:media] relative min-h-[130px] @md/card:min-h-full bg-tgx20-cell">
            <img src="https://images.unsplash.com/photo-1447752875215-b2761acb3c5d?w=500&h=500&q=80&auto=format&fit=crop" alt="Trail winding through coastal pine woodland" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
          </div>
          <div class="[grid-area:body] p-4 flex flex-col gap-2">
            <p class="text-[0.64rem] font-semibold tracking-[0.14em] uppercase text-tgx20-link">Trail guide</p>
            <h3 class="text-[clamp(0.92rem,4.5cqi,1.2rem)] font-semibold text-tgx20-ink leading-[1.25]">The coast path, in three days</h3>
            <p class="text-[0.8rem] leading-[1.55] text-tgx20-mut">Same markup, same stylesheet. The card asked its container — not the viewport — how much room it has, and chose the horizontal arrangement.</p>
            <a href="#0" class="mt-auto inline-flex items-center gap-1 min-h-11 text-[0.8rem] font-semibold text-tgx20-link no-underline hover:underline underline-offset-4 focus-visible:outline-2 focus-visible:outline-tgx20-link focus-visible:outline-offset-2 rounded">Read guide <span aria-hidden="true">→</span></a>
          </div>
        </article>
      </div>
    </main>
    <aside class="flex flex-col gap-2.5">
      <p class="font-tgx20-mono text-[0.66rem] text-tgx20-mut">aside · narrow → stacked</p>
      <div class="@container/card">
        <article class="grid [grid-template-areas:'media'_'body'] @md/card:[grid-template-areas:'media_body'] @md/card:grid-cols-[150px_minmax(0,1fr)] rounded-2xl overflow-hidden bg-white border border-tgx20-edge shadow-[0_12px_28px_-22px_oklch(0.45_0.05_45/0.9)]">
          <div class="[grid-area:media] relative min-h-[130px] @md/card:min-h-full bg-tgx20-cell">
            <img src="https://images.unsplash.com/photo-1447752875215-b2761acb3c5d?w=500&h=500&q=80&auto=format&fit=crop" alt="Trail winding through coastal pine woodland" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
          </div>
          <div class="[grid-area:body] p-4 flex flex-col gap-2">
            <p class="text-[0.64rem] font-semibold tracking-[0.14em] uppercase text-tgx20-link">Trail guide</p>
            <h3 class="text-[clamp(0.92rem,4.5cqi,1.2rem)] font-semibold text-tgx20-ink leading-[1.25]">The coast path, in three days</h3>
            <p class="text-[0.8rem] leading-[1.55] text-tgx20-mut">Identical component, adapted by its container.</p>
            <a href="#0" class="mt-auto inline-flex items-center gap-1 min-h-11 text-[0.8rem] font-semibold text-tgx20-link no-underline hover:underline underline-offset-4 focus-visible:outline-2 focus-visible:outline-tgx20-link focus-visible:outline-offset-2 rounded">Read guide <span aria-hidden="true">→</span></a>
          </div>
        </article>
      </div>
    </aside>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tgx20-bg: #faf4ee;
  --color-tgx20-bg: oklch(0.965 0.012 60);
  --color-tgx20-cell: #eadfd3;
  --color-tgx20-cell: oklch(0.9 0.02 60);
  --color-tgx20-edge: #e7cdb6;
  --color-tgx20-edge: oklch(0.87 0.05 60);
  --color-tgx20-ink: #3a2a1e;
  --color-tgx20-ink: oklch(0.3 0.04 45);
  --color-tgx20-mut: #6b5648;
  --color-tgx20-mut: oklch(0.47 0.03 45);
  --color-tgx20-link: #a1481f;
  --color-tgx20-link: oklch(0.52 0.15 40);
  --font-tgx20-sans: 'Inter Tight', system-ui, sans-serif;
  --font-tgx20-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tgx-20 {
  width: 100%;
  min-height: 100svh;
}
```

How this works

The wrapper is queried; the child is styled. An element cannot query itself, so the holder declares the container and the card carries the @md/card: variants.

Both cards are the same markup. Copy the class list into a 2fr region and a 1fr region — the two renderings ARE the proof, which is why this demo shows them side by side.

Make it yours

  • Add a third tier with @2xl/card: for a full-bleed feature variant.
  • Name containers uniquely when nesting cards inside card lists.
  • This composes with RAM: cards in an auto-fit grid self-adapt as tracks resize.

Gotchas — read before shipping

  • A container cannot size itself from its contents on the queried axis — width must come from context.
  • Query the WRAPPER, style the CHILD: @md/card: on the container element never matches.
  • Tailwind's @md is a CONTAINER size, not a viewport breakpoint; the /card suffix is the disambiguator.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Size container queries are Baseline 2023; the stacked layout is the no-query fallback.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Arbitraryneeds bracket syntax

Search CodeFronts

Loading…