The Single Line That Does Everything
The simulation index pages list dozens of cards. On a wide monitor
they should appear in 4 or 5 columns; on a phone, 1 or 2. The classic
approach requires three or four @media breakpoints. The
CSS Grid approach needs exactly this:
.sim-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 1rem;
}
That's it. No breakpoints. No JavaScript. Resize the browser and the grid reflows automatically.
Live Demo (drag the corner to resize)
↔ Drag the right edge of the demo box to see the grid reflow.
How It Works
repeat(auto-fill, …) tells the browser: "create as many
columns as fit." minmax(260px, 1fr) means: "each column
is at least 260px wide, but grows equally to fill remaining space."
So at 800px wide with a 1rem gap, you fit 2 × 260px + gap = ~532px → 3 columns almost fit → 2 columns each growing to ~395px. The math works out automatically.
auto-fill vs auto-fit
There are two keywords — they only differ when items don't fill a full row:
-
auto-fill— keeps empty columns in the implicit grid. Cards don't stretch past their max-width on large screens. -
auto-fit— collapses empty columns. If you have 2 cards in a 4-column space, they'll each take half the width withauto-fit, but stay 260px withauto-fill.
Use auto-fill when you have a known minimum card width
and don't want cards to stretch too wide. Use
auto-fit when you want cards to always fill the full
container.
Adding a max-width cap
/* Prevent very wide cards on large screens */
.sim-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
gap: 1rem;
max-width: 1400px;
margin-inline: auto;
}
/* Or clamp the card width directly: */
.sim-card {
max-width: 380px;
}
The Card Itself
The card pattern used here: hover border glow, aspect-ratio thumbnail, scale transform, and padding that fits the text without overflow:
.sim-card {
background: var(--color-surface-2);
border: 1px solid var(--color-border);
border-radius: 14px;
overflow: hidden;
text-decoration: none;
color: var(--color-text);
transition: border-color 0.15s ease, transform 0.15s ease;
}
.sim-card:hover {
border-color: var(--color-accent);
transform: translateY(-2px);
}
.sim-card-thumb {
aspect-ratio: 16 / 9;
background: var(--color-surface);
overflow: hidden;
}
.sim-card-thumb img {
width: 100%; height: 100%;
object-fit: cover;
display: block;
}
.sim-card-body {
padding: 0.9rem 1rem;
}
.sim-card-title {
font-size: var(--text-sm);
font-weight: 700;
margin-bottom: 0.25rem;
}
A11y note: Make the entire card a link (<a>
wrapping all content), not a button. Screen readers announce it as a
link and keyboard users can tab to it naturally. Avoid
pointer-events: none on inner elements — it breaks text
selection.