Free · Fast · Privacy-first

CSS Card Grid Layout

A card grid needs three things at once: equal-width columns, equal-height cards across each row, and automatic column count adjustment as the viewport narrows. Older approaches with floats and percentage widths could deliver one or two of these but rarely all three without JavaScript helpers, fixed heights, or per-breakpoint column count overrides. CSS Grid delivers all three from a single container ruleset and never needs to be told how many columns to draw at any specific width. FixTools generates the correct combination of auto-fill, minmax, gap, and align-items to produce a production-ready card grid without any additional CSS or JavaScript. The same ruleset works for product listings, blog post grids, portfolio thumbnails, team member directories, and any other grid of similar-shape cards.

Cost
Free forever
Sign-up
Not required
Processing
In your browser
Privacy
Files stay local

Generates repeat(auto-fill, minmax()) for automatic column adjustment

🔒

Sets align-items: stretch for equal-height cards per row

Configurable minimum card width and gap values

CSS Tool

Grid Flexbox Builder

All processing happens in your browser — your files are never uploaded to any server.

🚀Open Grid Flexbox Builder

100% Free · No account · Works on any device

What a Card Grid Needs and Why CSS Grid Is the Right Tool

A card grid requires three specific behaviours that are difficult to achieve simultaneously with other layout techniques. First, columns must be equal width so cards line up in consistent columns. Second, all cards in a row must be the same height, so the grid looks structured even when card content varies in length. Third, the column count must adjust automatically as the viewport narrows, reducing from five columns on a wide desktop to two or one on a narrow mobile screen. Earlier techniques using floats or inline-block required JavaScript for equal heights and media queries for each column count change. CSS Grid addresses all three requirements from a single container ruleset with no JavaScript and no breakpoint-specific column count overrides.

The CSS Grid solution for a card grid uses repeat(auto-fill, minmax(280px, 1fr)) for the grid-template-columns value. repeat(auto-fill) tells the browser to calculate column count from container width, creating as many columns as fit. minmax(280px, 1fr) sets each column to at least 280px and allows it to expand equally to fill remaining space. This produces automatic column adjustment without media queries. align-items: stretch (the Grid default) makes all cards in a row as tall as the tallest card, which produces the equal-height behaviour. gap sets consistent spacing between cards in both dimensions. The complete ruleset is display: grid, grid-template-columns, gap, and optionally align-items: stretch.

CSS Grid outperforms Flexbox for card grids primarily because of how it handles equal heights across rows. In a wrapping Flexbox container, each row is independent: the cards in row two do not know the height of cards in row one. Row heights are determined separately, which means cards in the same Flexbox row share equal height, but there is no mechanism to enforce that different rows have the same height. CSS Grid treats all rows as part of the same two-dimensional structure. Cards in the same grid row automatically receive the same height because they share row tracks. For cards with variable content (different length descriptions, missing images, varying title lengths), CSS Grid produces a visually consistent grid without any additional workarounds.

The card structure inside each grid cell deserves a small amount of attention too. The card itself is usually a Flexbox column with flex-direction: column applied to the article or div that holds the image, title, description, and call-to-action. This inner Flexbox lets you push the call-to-action button to the bottom of the card with margin-top: auto so action buttons align horizontally across the row even when descriptions have different lengths. Grid handles the outer card-to-card alignment and equal heights, and the inner Flexbox handles the alignment of elements within each individual card. The two layout systems compose cleanly because each one is solving a different problem, and the resulting card looks polished without any height calculations or magic numbers in your CSS.

How to use this tool

💡

Set your minimum card width in the generator (typically 250px to 300px), add a gap value, leave align-items on stretch, and copy the CSS. Paste the ruleset onto your card container element.

How It Works

Step-by-step guide to css card grid layout:

  1. 1

    Set the minimum card width

    Enter the minimum width a card should be before the browser drops to fewer columns. For content-heavy cards, 280px to 320px is typical; for compact data cards, 200px to 240px.

  2. 2

    Choose auto-fill or auto-fit

    Select auto-fill to keep consistent card widths on partial rows. Select auto-fit if you want the last row of cards to stretch and fill the container width.

  3. 3

    Set the gap value

    Enter a gap for spacing between cards. A consistent gap of 16px to 24px works for most card grids. The gap is factored into the column count calculation automatically.

  4. 4

    Copy the container ruleset

    Click Copy CSS to copy the grid container ruleset with display: grid, grid-template-columns, gap, and align-items. Paste it onto your card wrapper element.

Real-world examples

Common situations where this approach makes a real difference:

E-commerce product listing

A product page uses repeat(auto-fill, minmax(260px, 1fr)) with gap: 20px and align-items: stretch. Product cards with different description lengths and optional badge labels all share the same row height. The add-to-cart button at the bottom of each card aligns across the row because each card is a Flexbox column container with the button pushed to the bottom using margin-top: auto.

Blog post preview cards

A blog index uses repeat(auto-fill, minmax(300px, 1fr)) with gap: 24px. Posts with featured images, posts with only a title and excerpt, and posts with video thumbnails all sit in the same grid. The equal-height behaviour ensures the grid looks structured even with inconsistent card content, and no JavaScript sets heights after the page loads.

Team member directory with profile cards

A company team page uses repeat(auto-fill, minmax(220px, 1fr)) with gap: 16px for compact profile cards. Cards contain a photo, name, title, and optional social links. Some members have two social links, others have four. All cards in a row share the same height automatically, and the grid drops from four to two to one column as the page narrows.

Portfolio project grid

A design portfolio uses repeat(auto-fill, minmax(340px, 1fr)) with gap: 12px and a slightly larger minimum width for project preview cards. On a 1400px wide container, four cards appear; on a 1024px container, three. The larger minimum prevents narrow cards that would make project thumbnails too small to read. align-items: start is chosen here so cards with brief descriptions are not artificially stretched into oversized boxes that draw attention away from the project images, which are the real content of the portfolio.

When to use this guide

Use this when building a grid of cards where all cards in a row must share equal height and the column count should adjust automatically at different viewport widths.

Pro tips

Get better results with these expert suggestions:

1

Use align-items: start for cards where natural height is preferred

align-items: stretch (the default) makes all cards in a row the same height. If cards contain only a title and a short action, stretched cards with large empty areas look wrong. Switch to align-items: start so cards are their natural height. Use stretch when cards have a button or price that should align to the bottom of the tallest card.

2

Push card footer content to the bottom with margin-top: auto

For equal-height cards with stretched alignment, add display: flex; flex-direction: column to each card and margin-top: auto to the bottom action element (such as a button or price tag). This pushes the action to the bottom of each card regardless of the card height, creating the aligned bottom-row effect that makes card grids look polished.

3

Set a max-width on the grid container for very wide viewports

At 2560px or wider, auto-fill creates many columns that may be too numerous for the content. Add max-width: 1400px and margin: 0 auto to the grid container to cap the maximum grid width and centre it on wide screens. Cards expand to fill the capped container width without becoming excessively wide on ultra-wide monitors.

4

Choose a minimum width that creates sensible column counts at target breakpoints

A 280px minimum creates roughly four columns at 1200px, three at 900px, two at 580px, and one at 280px. A 220px minimum creates five columns at 1200px. Calculate the column count at your most common viewport widths before finalising the minimum: (container width minus total gap) divided by minimum column width gives approximate column count.

FAQ

Frequently asked questions

Apply display: grid to the card container with a grid-template-columns value that uses auto-fill and minmax. The default align-items: stretch makes all cards in each row the same height as the tallest card in that row. No JavaScript and no fixed heights are needed. Grid calculates equal heights automatically because all cells in a row share the same row track.
repeat(auto-fill, minmax(280px, 1fr)) with gap: 20px is the most common starting point for card grids. Adjust the minmax minimum based on your card content: smaller values for compact cards, larger values for content-heavy cards with images and descriptions. The 1fr maximum ensures columns expand equally to fill remaining space after the auto-fill calculation.
CSS Grid enforces equal heights across all cards in a row because cells share row tracks. A wrapping Flexbox row has equal heights within that row, but each row is independent of adjacent rows. For cards with variable content, Grid ensures that all rows look consistent without JavaScript. Flexbox also has no direct equivalent to auto-fill: you must use percentage-based flex-basis values and media queries to control column count.
Set each card to display: flex with flex-direction: column. Add margin-top: auto to the button or action element inside the card. This pushes the action to the bottom of the card's available height. When the Grid stretches all cards in a row to equal height, the stretched space appears above the button, which sits flush at the bottom of each card regardless of how much content precedes it.
Use auto-fill for most card grids. It creates empty column tracks on partial rows, which keeps card widths consistent: a last row with two cards in a four-column grid shows two cards at the same width as cards in full rows above. auto-fit collapses empty tracks and stretches the two remaining cards to 50% width each, which often looks too wide. auto-fit is appropriate when you specifically want the last row to fill the container.
Add max-width to the grid container and centre it with margin: 0 auto. For example, max-width: 1400px; margin: 0 auto limits the grid to 1400px and centres it on wider viewports. Cards continue to use the auto-fill column calculation within the capped container width. Without a max-width, auto-fill on a 2400px screen may produce more columns than your design requires.
CSS Grid does not natively support masonry (variable-height items packed without uniform row heights) in widely supported browser versions. The CSS specification includes a masonry keyword for grid-template-rows, but it is not yet available in production browsers. For masonry layouts today, the common alternatives are a JavaScript masonry library, CSS columns with column-count, or a third-party CSS-only technique. For standard equal-height card grids, CSS Grid is the correct and fully supported choice.
Gap values of 16px to 24px work for most card grids. A tighter 12px gap suits dense information grids such as small data cards or compact thumbnails. A looser 24px to 32px gap works for editorial content cards where visual breathing room is part of the design. Use a consistent gap in both row and column directions unless your design specifically requires more vertical than horizontal spacing between cards, in which case set row-gap and column-gap separately rather than the combined gap shorthand.
Add an opacity and transform transition on each card and toggle a visible class using IntersectionObserver as the card scrolls into view. The Grid layout itself is unaffected by transforms because transform does not change layout. A common pattern fades the card from opacity 0 with a translateY(8px) up to opacity 1 and translateY(0) over 240ms. Stagger the delay slightly between adjacent cards using a CSS custom property indexed off the nth-child position to produce a gentle cascade rather than all cards appearing at once. Keep the animation subtle so it does not slow down repeated page visits.
Yes. CSS Grid only draws cells where it has children, so a grid with eight cards in a four-column layout shows two full rows. There are no empty placeholder cells unless you add them explicitly. If you need a placeholder card (for a "Coming soon" tile or an upload-new-item action), simply add another child element with the same outer wrapper class as the real cards. The grid treats it identically and lays it out next to the others. Removing a card later does not require any layout adjustment because the auto-fill column calculation simply produces one fewer column slot or moves the next card up.

Related guides

More use-case guides for the same tool:

Ready to get started?

Open the full Grid Flexbox Builder — free, no account needed, works on any device.

Open Grid Flexbox Builder →

Free · No account needed · Works on any device