CSS grid not equal height problems usually happen when grid items are not stretching, inner cards do not use height 100%, rows are being compared incorrectly, or card content is not arranged with a consistent internal layout.
CSS Grid Equal Height Fix
Why is my CSS grid not equal height?
CSS Grid can make columns line up beautifully, but equal-height cards still break when one card has more text, another has a taller image, or the grid item stretches while the card inside it does not. The fix depends on what “equal height” means: equal inside the same row, equal across all rows, or equal internal content alignment.
- CSS Grid
- equal height cards
- align-items
- grid-auto-rows
What the bug looks like
Cards in a grid look uneven, buttons sit at different levels, or shorter cards do not stretch to match taller cards.
Why it happens
The grid, grid item, card wrapper, and inner content layout are not all following the same height strategy.
What usually fixes it
Use stretch alignment, make the card fill the grid area, and use a flex column inside the card for consistent content alignment.
align-items:start prevents equal height stretching
CSS Grid items stretch by default. But if the grid container uses align-items:start, each item keeps its own content height. That makes cards in the same row look uneven.
Broken code
Stretch disabled.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
align-items: start;
}
Broken visual result
The row does not stretch items to the same height.
align-items:start tells the grid items not to stretch vertically.Correct code
Stretch items.card-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
align-items: stretch;
}
Fixed visual result
The grid items stretch to match the tallest item in the row.
The grid item is equal height, but the card inside is not
Sometimes the grid item is stretching correctly, but the visible card inside it still uses content height. In that case, make the card fill the grid item with height:100%.
Broken code
Inner card stays short.grid {
display: grid;
align-items: stretch;
}
.card {
/* visible card still uses content height */
}
Broken visual result
The grid area may be equal, but the visible card does not fill it.
Correct code
Card fills grid item.grid {
display: grid;
align-items: stretch;
}
.card {
height: 100%;
}
Fixed visual result
The visible card fills the grid area, so the row looks equal.
You expect all rows to have the same height
CSS Grid naturally equalizes items inside the same row. It does not always make every row in the whole grid the same height. If you want rows across the grid to match, use grid-auto-rows:1fr carefully.
Broken code
Rows use content height.card-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: auto;
gap: 16px;
}
Broken visual result
Each row follows its own tallest content.
Correct code
Equal implicit rows.card-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-auto-rows: 1fr;
gap: 16px;
}
.card {
height: 100%;
}
Fixed visual result
Implicit rows can share the available row height pattern.
grid-auto-rows:1fr only when equal row height is really the visual goal.The cards are equal height, but the content inside is not aligned
Sometimes the card heights are equal, but the CTAs, badges, or prices appear at different vertical positions. That is an internal card layout problem. Use a flex column inside the card and push the CTA to the bottom.
Broken code
Content stacks naturally.card {
height: 100%;
}
.card-button {
/* button follows content */
}
Broken visual result
The card boxes match, but the internal buttons do not line up.
Correct code
Flex column card.card {
height: 100%;
display: flex;
flex-direction: column;
}
.card-button {
margin-top: auto;
}
Fixed visual result
The card content uses a column layout, so CTAs line up.
A production-minded equal-height CSS Grid pattern
A strong equal-height card grid uses responsive tracks, stretch alignment, safe column sizing, cards that fill their grid area, and flex column content inside each card.
Premium code
Equal-height card system.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
grid-auto-rows: 1fr;
align-items: stretch;
gap: clamp(16px, 2vw, 24px);
}
.card-grid > * {
min-width: 0;
}
.card {
height: 100%;
display: flex;
flex-direction: column;
min-width: 0;
}
.card-media {
aspect-ratio: 16 / 9;
object-fit: cover;
}
.card-content {
display: flex;
flex: 1;
flex-direction: column;
}
.card-action {
margin-top: auto;
}
Premium visual result
The grid, cards, and inner content all follow the same height strategy.
Fast practical rule
If CSS grid is not equal height, check align-items first. Then make the visible card use height:100%. If the card content still looks uneven, use display:flex, flex-direction:column, and margin-top:auto for bottom-aligned CTAs.
Debug checklist
- Check whether the grid has
align-items:start,center, or another value that prevents stretching. - Use
align-items:stretchwhen same-row equal height is desired. - If the visible card is nested inside the grid item, add
height:100%to the card. - Use
display:flexandflex-direction:columninside cards when buttons need to align at the bottom. - Use
margin-top:autofor card CTAs that should sit at the same vertical level. - Use
grid-auto-rows:1fronly when equal row height across multiple rows is actually needed. - Normalize image areas with
aspect-ratioor consistent media height. - Keep responsive behavior in mind: equal-height desktop cards may stack naturally on mobile.
align-items:start and test whether the grid items stretch.height:100%.Final takeaway
A CSS grid not equal height problem is usually not solved by forcing a random fixed height. The real fix is to know which level needs equal height: the grid item, the visible card, the grid row, or the content inside the card.
Let grid stretch the outside, make the card fill the grid area, and use flex inside the card for aligned internal content. That gives you equal-height cards without fragile fixed-height hacks.