Pin a card footer to the bottom of an equal-height grid
Cards in a grid have different amounts of text, so their prices and links land at ragged heights. Two CSS lines pin every footer to the bottom, no fixed heights and no 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, no matter how long the text above them runs.
What doesn’t work
The tempting fixes are all 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 as separate.
First, equal height. 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. You usually get equal height for free.
Second, bottom alignment 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 whole 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; the footer doesn’t move.
The lesson
Keep the two jobs separate in your head. Equal height is the parent’s job (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, and it’s worth committing to memory so you stop re-deriving it every time.
Discussion
Powered by GitHub. Sign in to leave a comment.