How to make elements in a row the same height?
Make cards or columns in a row the same height with flexbox or grid, push their buttons to the bottom, and line up titles and text across cards with subgrid.
Put the elements in a flex container. Flex items in a row already stretch to the height of the tallest one, because align-items: stretch is the default:
.cards {
display: flex;
gap: 24px;
}You don't need fixed heights or JavaScript. If the items still end up with different heights, something is overriding the stretch:
align-itemson the container, oralign-selfon an item, is set tocenter,flex-startor a similar value.- The item has a fixed
height, which stretching doesn't override. - The visible card isn't the flex item. If each card sits inside a wrapper, such as an
<li>, the wrapper stretches but the card inside doesn't. Give the cardheight: 100%. That works because a stretched flex item counts as having a definite height. - With
flex-wrap: wrap, each line stretches on its own, so cards on different lines can have different heights.
Grid
Grid items in the same row stretch the same way. Add grid-auto-rows: 1fr when every row should be as tall as the tallest row in the whole grid, not only the tallest item in its own row:
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
grid-auto-rows: 1fr;
gap: 24px;
}This is also the answer for layouts that wrap onto several lines, where flex can't match heights across lines.
Push the button to the bottom of the card
Equal-height cards still look uneven when some have less text, because the button lands at a different spot in each card. Make the card a flex column and give the button margin-top: auto, which takes all the free space above it:
<article class="card">
<h3>Starter</h3>
<p>For side projects and small sites.</p>
<a class="card-button" href="/signup">Choose plan</a>
</article>.card {
display: flex;
flex-direction: column;
gap: 12px;
}
.card-button {
margin-top: auto;
align-self: flex-start;
}align-self: flex-start stops the link from stretching across the full width of the card. Remove it if you want a full-width button.
Line up titles and text across cards with subgrid
Flex can't align the parts of different cards with each other. If one title wraps onto two lines, the text in that card starts lower than in the others. Subgrid fixes that: each card spans three rows of the parent grid and uses those rows for its own children, so the tallest title in the row sets the title height for every card.
<div class="plans">
<article class="plan">
<h3>Starter</h3>
<p>For side projects and small sites.</p>
<a href="/signup?plan=starter">Choose Starter</a>
</article>
<article class="plan">
<h3>Team plan for growing companies</h3>
<p>Everything in Starter, plus roles and shared billing.</p>
<a href="/signup?plan=team">Choose Team</a>
</article>
<article class="plan">
<h3>Enterprise</h3>
<p>Single sign-on, audit logs and a dedicated contact.</p>
<a href="/contact">Talk to us</a>
</article>
</div>.plans {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 24px;
}
.plan {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid;
row-gap: 12px;
padding: 24px;
border: 1px solid #e5e7eb;
border-radius: 12px;
}
.plan h3,
.plan p {
margin: 0;
}
.plan a {
justify-self: start;
}A few things to know:
- The number in
span 3must match the number of children in each card. If you add a price, usespan 4. - A subgrid uses the parent's
gapby default.row-gapon the card overrides it for the space inside the card, while the parent'sgapstill separates the cards. justify-self: startkeeps the link from stretching across the card, the same jobalign-selfdid in the flex version.
Subgrid is supported in all major browsers (Can I Use), so there's no reason left for JavaScript that measures and equalizes heights.