01. Tailwind Stats Dashboard KPI Grid (opens in a new tab)
style="--accent:#7c3aed" stays an inline custom property, and the accent bar, the border-on-hover and every sparkline bar read it back through bg-[var(--accent)].15 Tailwind card grid layouts — auto-fit and multi-column archives, asymmetric and glass bento boxes, equal-height product and pricing grids, masonry and photo-collage walls, testimonial and team directories, KPI dashboards, magazine features, and 3D hover-flip decks. Scoped under .tcg-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.
Related15 CSS Card Grid Layouts30 CSS Grid Layouts15 CSS Flexbox Layouts6 CSS Bento Grid Layouts21 Tailwind CSS Pricing Sections
Premium upgradePartner: Untitled UI
Affiliate linkBuilding a whole Tailwind app, not just this component?
You just browsed 15 Tailwind card grid layout. Untitled UI Pro unlocks 5,000+ components and sections and 250+ page examples for React, styled with Tailwind CSS v4. One licence is a one-time $349 with lifetime updates; teams start at $999.
Untitled UI React. We may earn a commission, at no extra cost to you.
style="--accent:#7c3aed" stays an inline custom property, and the accent bar, the border-on-hover and every sparkline bar read it back through bg-[var(--accent)].col-start-1 col-span-2 row-start-1 row-span-2 — so the collage rhythm is readable in the markup, and the readability overlay every photo grid ships is one after: chain instead of a pseudo-element block.flex flex-col with flex-1 on the list and mt-auto on the button. The featured tier's whole identity is five utilities: scale-104, a two-pixel accent border, a shadow, z-1, and max-[860px]:order-first.bg-tcg11-featbg text-tcg11-featink) and its children inherit, so the CSS version's six .card--featured .x descendant rules shrink to two text-* overrides.col-span-full, col-span-8, col-span-4.@theme, which is exactly the case for a token: one value, used by many elements, meaningful across the design.bg-[…padding-box,…border-box] utility that reads its colour from a per-tile --glow.before: layer that wipes down on hover via clip-path: inset(). Every one of the CSS version's twelve placement rules moves onto its tile, so the bento's weighting is finally readable in the markup.items-stretch on the grid, h-full flex flex-col on the card, and mt-auto on the price row. The port's value here is that the contract is now visible on the elements that make it.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.repeat(auto-fit,minmax(280px,1fr)) stays arbitrary, everything else becomes a utility.w-21 h-21 and -mt-12.5) finally sit on the same element.perspective-*, transform-3d, backface-hidden and rotate-y-* as real utilities, so the entire 3D scene is expressible without touching the stylesheet.--edge — 0 for flat frosted panels, 1 for a pronounced lensed rim. The animation lives in @theme as --animate-tcg15-bg, which is how v4 mints an animate-* utility from a keyframe.grid grid-cols-[repeat(auto-fit,minmax(16rem,1fr))]. The minmax(16rem,1fr) says every column is at least 16rem wide and at most one equal fraction of the row; auto-fit then packs in as many 16rem columns as the container allows and stretches them to fill. Widen the container and a new column appears, narrow it and columns drop away — all from a calculation the browser runs for free, with no @media rules to maintain. Swap auto-fit for auto-fill only when you want the empty track slots kept, so a short last row stays left-aligned instead of stretching to fill the width. Set the gutter with gap-6 and the archive reflows fluidly between one and four-plus columns.items-stretch. What isn't automatic is where the button lands inside the card, because a two-line title pushes it down while a one-line title leaves it high. Make each card a flex column with flex flex-col, then push the CTA to the bottom with mt-auto on the button, or let the description soak up the slack with grow. Now every Add-to-Cart and every pricing CTA sits on the same horizontal axis regardless of title length or feature count. The common mistake is forcing a fixed h-64 on the card — that clips long content. Let the row height come from the tallest sibling instead.columns-2 sm:columns-3 lg:columns-4 on the wrapper, then break-inside-avoid mb-6 on each card so a tile never splits across two columns. Cards keep their natural height and stack tightly, which is the whole point: a wall of mixed aspect ratios with no ragged bottom edge. The catch is reading order — multi-column fills top-to-bottom down column one, then column two, so the visual order is not the DOM order. That's fine for a photo gallery but wrong for anything sequential like ranked results. Native grid masonry via grid-template-rows: masonry preserves source order but isn't shipped widely enough to rely on, so column flow stays the safe default. Use gap-6 to set the column gutter.grid grid-cols-4 — then give the feature tile col-span-2 row-span-2 so it occupies a 2×2 block while the smaller tiles flow around it. The bug everyone hits first: the tall tile doesn't actually get taller, because grid rows size to their content by default, so row-span-2 spans two short rows. Fix it by making the rows equal with auto-rows-fr, or an explicit grid-rows-*, which gives every row a 1fr height for the span to double. On narrow screens collapse to a single column with grid-cols-1 and drop the spans, or the hero tile overflows its track. Keep spacing consistent with one gap-4 on the parent rather than margins on individual tiles.-mt-12, a little more than half its own height, which lifts it above the card's top border so it breaks the edge. Two things trip people up. First, if the card carries overflow-hidden — common when you're clipping a rounded corner or a background image — the overflowing half of the avatar gets clipped away; keep the card overflow-visible and clip the image with a separate inner wrapper instead. Second, give the avatar a ring in the card's own surface colour with ring-4 ring-white or your token, so it reads as sitting on top rather than merging into whatever is above. Add relative if a sibling needs to stack beneath it, and leave enough top padding for the name and role that follow.[perspective:1000px] — and an inner wrapper carries [transform-style:preserve-3d] plus a transition. On hover you rotate that wrapper with group-hover:[transform:rotateY(180deg)], driven by a group class on the outer element. Both faces are absolutely positioned and stacked, each with [backface-visibility:hidden] so it hides when turned away; the back face starts pre-rotated with [transform:rotateY(180deg)] so it reads upright after the flip. The classic bug is the back face showing through mirror-reversed — that's a missing backface-visibility:hidden on one of the two faces. Give both faces absolute inset-0 and matching height, or the card collapses to zero height once the faces leave normal flow.:hover, and a touch user has no hover at all, so anything living only on the back face is invisible to both. Two rules. First, never put essential information solely on the back — treat the flip as progressive enhancement over content already legible on the front. Second, make the flip focus-driven as well: add focus-within:[transform:rotateY(180deg)] alongside the hover variant, and put a real focusable element — a <button> or <a> — inside so the card can receive focus at all. Respect motion-reduce:transition-none so the rotation doesn't spin for users who asked for less motion. Screen readers read both faces in DOM order regardless of the visual flip, so keep that order sensible.grid-cols-3 collapsing to grid-cols-1 on mobile is clearer and never surprises you. Two failure modes worth knowing. With auto-fit, a single leftover item stretches to the full container width, which looks broken for one lone card; auto-fill keeps the empty tracks so it stays column-width. And minmax(16rem,1fr) can overflow its track when a card holds something unshrinkable — a long unbroken string or a wide image — because 1fr carries a min-content floor; switch to minmax(0,1fr) to let it shrink. For anything where the count and order are fixed and sequential, an explicit grid or even flex reads more predictably than letting the browser choose the column count.15 hand-coded CSS aspect-ratio demos for video embeds, product galleries, IAB ad slots, native dialogs, and CLS-safe placeholders: 16:9 iframe YouTube embed with click-to-load facade + up-next rail, 21:9 full-screen hero video with min-height/max-height:100svh guardrails + Ken Burns drift, 1:1 Instagram-style square grid with 2×2 feature tile, 4:3 magazine card image cover, 9:16 vertical stories rail (TikTok/Reels/Shorts pattern) with scroll-snap + segment bars, 4:5 apparel product image gallery with radio-driven state + 1:1 thumbnails, 1:1 zoom thumbnail carousel with pointer-tracked --zx/--zy magnifier, prevent-layout-shift placeholder with live PerformanceObserver CLS meter (before/after side-by-side lab), dynamic content fallback with three policies (bend/strict/auto) via :has() toggle, IAB ad banner slots (728×90 leaderboard, 300×250 medium rectangle, 300×600 half-page, 320×50 mobile) with skeletons + container-query mobile swap, responsive modal dialog sized min(92vw, 88svh×16/9, 1080px) with @starting-style animation, responsive OpenStreetMap iframe wrapper with 16:9 → 1:1 container-query narrow swap, media query orientation live HUD + resize:both container-ratio playground, object-fit logo cloud with contain/cover/fill switcher via :has(), and side-by-side padding-top hack (height:0 + padding-top:56.25%) → modern aspect-ratio migration comparison with live ratio picker. 11 truly Pure CSS + 4 with a tiny optional vanilla JS snippet (facade swap, pointer magnifier, CLS meter, native dialog). Every demo is scoped under a unique .car-NN prefix so it drops into any project without CSS collisions, ships prefers-reduced-motion guards, and is framework-agnostic (works as-is in React, Vue, Svelte, Astro, Next.js, Remix, or plain HTML).
6 production CSS bento grid layouts with 12 hand-coded designs — Apple-style product showcase, SaaS feature value-prop matrix, analytics dashboard overview, creative portfolio, e-commerce category hub, and link-in-bio social hub. Each topic ships 2 sub-variants side-by-side so visitors see both a keynote aesthetic and a paper-doc variant at once. Container queries, CSS Grid, zero dependencies, copy-paste ready.
20 hand-coded CSS blog and editorial layouts for magazine homepages, news sites, personal archives, newsletter back-issues, recipe and podcast blogs, developer tutorials, and long-form journalism. Covers a magazine homepage with hero plus editor-picks rail, a news homepage with breaking-news ticker, blog archives with sticky year separators, Substack-style issue-numbered archives, recipe card grids with prep-time badges, podcast episode lists with waveforms, long-form articles with scroll-driven reading progress, drop caps and floated pull quotes via first-letter, Medium-style 65ch centred reader layouts, dev tutorials with a sticky code panel beside prose, interview transcripts with alternating speakers, case-study pages with stat counters, video blogs with an episode rail, full-bleed photo essays, news articles with sticky related-stories sidebars, documentation pages with prev/next chapter nav, a standalone blog post card, a scroll-snap category filter bar, an inline newsletter callout that breaks out of the prose column, and a horizontal featured-post rail. 12 are pure CSS with zero JavaScript. Every layout is scoped under a .bl-NN prefix for no-collision pasting, guards prefers-reduced-motion, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.