Align card footers to the bottom of a CSS grid with margin-top: auto

2 min read CSSFlexbox

Cards in a row hold different amounts of text, so their prices and links sit at ragged heights. Make each card a full-height flex column and give the footer margin-top: auto. It needs no fixed heights or JavaScript.

TL;DR · THE FIX

Equal height comes from the grid stretching the cards; bottom alignment comes from margin-top: auto on the footer inside a flex-column card. Make the card display: flex; flex-direction: column; height: 100%, then put margin-top: auto on the footer.

The symptom

A grid of cards, each ending in a footer: a price and a “View” link, or a “5 min read” line. The cards hold different amounts of text, so the footers land at different heights and the row looks ragged. I wanted every footer pinned to the bottom so they line up across the row, however long the text above them runs.

What doesn’t work

The tempting fixes are brittle. Hardcoding a card height clips the long ones and leaves gaps under the short ones. position: absolute on the footer drops it out of flow, so it overlaps content at narrow widths. Padding hacks need a different magic number at every breakpoint. All of them fight the content instead of letting it flow.

The fix

Two independent pieces, and it helps to see them separately. Equal height comes from the parent: in a CSS grid or a flex row, cards in the same row already stretch to the tallest one, because align-items: stretch is the default, so you usually get that for free. Bottom alignment happens inside each card. Make the card a full-height flex column, then give the footer an automatic top margin:

.card {
  display: flex;
  flex-direction: column;
  height: 100%;        /* fill the equal-height grid track */
}

.card .footer {
  margin-top: auto;    /* absorb the slack, pin to the bottom */
}

In Tailwind that’s flex flex-col h-full on the card and mt-auto on the footer row.

margin-top: auto is the trick. In a flex column, an auto margin eats all the free space on that side, so it shoves the footer down to the bottom and parks it there. The text above can be one line or six and the footer doesn’t move.

The lesson

Keep the two jobs separate. Equal height is the parent’s job, since the grid or flex row stretches the cards. Bottom alignment is the child’s job, margin-top: auto inside a flex column. No fixed heights, no JavaScript, responsive by default. It’s the same pattern holding the price rows and “min read” lines in place on the cards across this site.

Related fixes

Discussion

Powered by GitHub. Sign in to leave a comment.