Build a responsive card grid
Start with native CSS. This example adapts its column count to the available width, keeps long titles inside each card, and works without a build tool. Save these files together and open index.html.
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Responsive card grid</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<h1>Project library</h1>
<ul class="cards">
<li><h2>Portfolio</h2><p>A home for your work.</p><a href="#portfolio">View portfolio</a></li>
<li><h2>Dashboard</h2><p>A workspace for daily tasks.</p><a href="#dashboard">View dashboard</a></li>
<li><h2>Documentation</h2><p>A guide for your users.</p><a href="#documentation">View documentation</a></li>
</ul>
</main>
</body>
</html>
The links are demonstration anchors; replace them with your real destinations before publishing.
styles.css
:root { --space: 1rem; --ink: #171717; --paper: #ffffff; }
* { box-sizing: border-box; }
body { margin: 0; color: var(--ink); background: var(--paper); font: 1rem/1.6 system-ui, sans-serif; }
main { max-width: 72rem; margin-inline: auto; padding: var(--space); }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); gap: var(--space); list-style: none; padding: 0; }
.cards li { min-width: 0; overflow-wrap: anywhere; padding: var(--space); border: 1px solid #737373; border-radius: .75rem; }
.cards h2 { margin-block: 0 .5rem; }
a { color: #1646c9; text-underline-offset: .2em; }
a:focus-visible { outline: 3px solid currentColor; outline-offset: 4px; }
The minimum column width is capped at the container width, so the grid can shrink below 16rem. Auto-fit adds columns only when they fit. CSS variables keep spacing and surfaces consistent. Flexbox is useful inside a card when content needs one-dimensional alignment; it does not replace the grid's column sizing.
Optional Tailwind 3 PostCSS setup
This separate path uses Tailwind 3.4.11, PostCSS 8.4.47, and Autoprefixer 10.4.20. It is an explicitly versioned older setup, not Tailwind 4 instructions. Use Node 22 and an empty directory.
npm init -y
npm install -D [email protected] [email protected] [email protected]
Create tailwind.config.cjs:
module.exports = { content: ["./index.html"], theme: { extend: {} }, plugins: [] };
Create postcss.config.cjs:
module.exports = { plugins: { tailwindcss: {}, autoprefixer: {} } };
Create input.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
In index.html, replace the list's class with grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4, and keep the styles.css link. Generate that file:
npx tailwindcss --postcss -i ./input.css -o ./styles.css
Re-run after changing classes, or add --watch during development. Tailwind 4 uses a separate PostCSS integration package and a different CSS entry. Follow the current official PostCSS guide for that version; do not mix the two configurations.
Check the outcome
Resize the native example to 320, 768, and 1280 pixels. At 320 it should show one column without page overflow; at wider sizes more columns should fit. For the Tailwind variant, verify one, two, and three columns at those widths. Tab to each link and confirm its focus outline remains visible. Test long text and 200% zoom. These examples demonstrate layout and focus; review your final content, colors, and destinations separately.