How to make a child element 100% height of its parent?
Why height: 100% often does nothing, and how to make a child fill its parent's height with flexbox, grid, an explicit height or absolute positioning.
Make the parent a grid container or a flex row. Grid items and flex items in a row stretch to fill the parent's height automatically, so you don't need height: 100% at all:
<aside class="sidebar">
<div class="panel">I fill the sidebar</div>
</aside>.sidebar {
display: grid;
min-height: 400px;
}
/* .panel is now at least 400px tall and full width */Why height: 100% does nothing
A percentage height is a percentage of the parent's height, and it only works when that height is definite, for example height: 400px or height: 50vh. If the parent's height is auto (it grows with its content) or is only set with min-height, the browser can't resolve the percentage and treats height: 100% as auto.
.sidebar {
min-height: 400px;
}
.panel {
height: 100%; /* behaves like auto */
}With an auto parent, the parent's height depends on the child, and the child's height would depend on the parent. CSS avoids that loop by ignoring the percentage.
Fix 1: flexbox
In a flex row, items stretch to the container's height, because align-items: stretch is the default:
.sidebar {
display: flex;
}
.panel {
flex: 1; /* also fill the width */
}In a column, give flex: 1 to the child that should take the remaining space:
.page {
display: flex;
flex-direction: column;
min-height: 100dvh;
}
.page main {
flex: 1;
}Stretching doesn't happen if the child has its own height or if align-items or align-self is set to something other than stretch. The same idea makes cards in a row equal, see how to make elements in a row the same height.
Fix 2: grid
A grid item stretches in both directions, as in the first example. With several children, size the rows:
.card {
display: grid;
grid-template-rows: auto 1fr;
min-height: 300px;
}The first row is as tall as its content, and the second row takes the rest.
Children inside a stretched grid or flex item can use height: 100% again, because browsers treat the stretched height as definite.
Fix 3: an explicit height on the parent
If the parent has a fixed height, percentages work:
.chart {
height: 320px;
}
.chart canvas {
height: 100%;
}If the child also has padding or a border, use box-sizing: border-box, or height: 100% plus the padding makes it taller than the parent. Vertical margins on the child cause the same overflow.
Fix 4: absolute positioning
.card {
position: relative;
}
.card-overlay {
position: absolute;
inset: 0;
}inset: 0 stretches the child over the parent's padding box, whatever the parent's height is. The child is taken out of the normal flow, though, so the parent doesn't grow to fit it. Use this for overlays, image backgrounds and clickable areas, not for main content.
The html, body and app root chain
For a full-page layout with percentages, every ancestor needs a height, including the wrapper your framework adds:
html,
body,
#root {
height: 100%;
}The wrapper is #root in a typical Vite React app and #__next in the Next.js Pages Router. Miss one level and the chain breaks. It's easier to skip percentages and use min-height: 100dvh on a flex or grid wrapper, as explained in how to make an element 100% of the screen height.
My recommendation: use grid when one child should fill the parent in both directions, and a flex column when one section should take the space that's left.