Question

How to Make a Div Fill Remaining Height in CSS

htmlcsshtml-table

Question

I am building a web application where the main content area should fill the remaining height of the viewport.

The page has two main sections:

  • a header area containing a logo and account information
  • a content area that should stretch from below the header to the bottom of the screen

The header can have an arbitrary height, so I cannot hard-code its size.

Right now I am using a table-based layout:

<table id="page">
  <tr>
    <td id="tdheader">
      <div id="header">...</div>
    </td>
  </tr>
  <tr>
    <td id="tdcontent">
      <div id="content">...</div>
    </td>
  </tr>
</table>
#page {
  height: 100%;
  width: 100%;
}

#tdcontent {
  height: 100%;
}

#content {
  overflow: auto; /* or overflow: hidden; */
}

This fills the full page height without requiring the whole page to scroll.

Also, elements inside the content area may use percentage heights. For example:

  • an element with height: 100% should fill the content area
  • two elements with height: 50% should each take half of the content area

If the header takes 20% of the screen height, then a table with height: 50% inside #content should take 40% of the screen height.

Is there a way to achieve this same effect without using a table for layout?

Short Answer

By the end of this page, you will understand how to make a section fill the remaining viewport height below a header with unknown height. You will learn why percentage heights often fail, how modern CSS layout tools like Flexbox solve this cleanly, and how to structure nested elements so height: 100% and other percentage-based heights work reliably.

Concept

In CSS, making one element fill the remaining height is a layout problem. The browser needs to know two things:

  1. the total available height
  2. how much space other elements already use

Traditional table layouts could do this automatically, which is why they were often used in older web apps. But modern CSS provides better tools for this, especially Flexbox.

The key idea is:

  • make the page take up the full viewport height
  • let the header size itself naturally
  • allow the content area to grow and fill whatever space is left

This is exactly what Flexbox is designed for.

A very common beginner issue is trying to solve this with height: 100% alone. That often does not work unless every parent element has a defined height. Percentage heights depend on the height of the parent, so if the parent's height is auto, the child's percentage height cannot be resolved the way you expect.

For layouts like:

  • header
  • main content fills the rest
  • nested panels inside content use percentage heights

Flexbox is usually the best solution.

Why this matters in real programming:

  • dashboard layouts often need a fixed or variable header with a scrollable body
  • admin apps commonly need side panels or content regions that fill available space
  • modals, editors, and split-view UIs often depend on parent-controlled height
  • data tables and charts frequently need to stretch inside a container

So this is not just about one div; it is about understanding how height flows through a layout.

Mental Model

Think of the page like a vertical stack of boxes inside a bookshelf with a fixed height.

  • The bookshelf is the viewport.
  • The header is a box that takes however much room it needs.
  • The content area is a flexible box that expands to fill all remaining shelf space.

Inside that flexible content box, you can then divide the space again:

  • one child can take 100%
  • two children can take 50% each

But this only works if the parent box has a real, known height.

So the rule of thumb is:

percentage heights work only when the parent has a definite height.

Flexbox helps create that definite remaining height automatically.

Take Quiz

Syntax and Examples

Basic Flexbox solution

<div class="page">
  <header class="header">
    Logo and account info
  </header>

  <main class="content">
    Main content
  </main>
</div>
html, body {
  height: 100%;
  margin: 0;
}

.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.header {
  padding: 16px;
  background: #ddd;
}

.content {
  flex: 1;
  overflow: auto;
  background: #f5f5f5;
}

What this does

  • height: 100vh makes .page as tall as the viewport
  • display: flex with flex-direction: column stacks children vertically
  • .header keeps its natural height
  • .content { flex: 1; } fills the remaining space

Example with percentage-height children inside content

<div class="page">
  <header class="header">Header</header>

  <main class="content">
    <div class="top-half">Top half</div>
    <div class="bottom-half">Bottom half</div>
  </main>
</div>
html, body {
  height: 100%;
  margin: 0;
}

.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.header {
  padding: 20px;
  background: #ccc;
}

.content {
  flex: 1;
  background: #eee;
}

.top-half,
.bottom-half {
  height: 50%;
}

.top-half {
  background: lightblue;
}

.bottom-half {
  background: lightgreen;
}

Because .content gets an actual height from the flex layout, its children can use percentage heights.

Common improvement: allow scrolling only in content

.content {
  flex: 1;
  overflow: auto;
  min-height: 0;
}

min-height: 0 is often important in Flexbox layouts when the content should shrink and scroll instead of overflowing.

Step by Step Execution

Consider this example:

<div class="page">
  <header class="header">My Header</header>
  <main class="content">
    <div class="box">I fill the remaining height</div>
  </main>
</div>
html, body {
  height: 100%;
  margin: 0;
}

.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.header {
  padding: 24px;
}

.content {
  flex: 1;
}

.box {
  height: 100%;
  background: peachpuff;
}

Step by step

  1. html and body are given full height.
  2. .page is set to 100vh, so it becomes exactly as tall as the viewport.
  3. .page uses display: flex and flex-direction: column, so its children are stacked vertically.
  4. .header takes up only the height it needs based on its content and padding.
  5. .content has flex: 1, so it grows to fill all the leftover vertical space.
  6. .box has height: 100%, so it becomes as tall as .content.

If the header grows taller, .content automatically becomes shorter. No manual height calculation is needed.

Example trace

Suppose the viewport is 800px tall.

  • header height becomes 120px
  • remaining space is 680px
  • .content becomes 680px tall
  • .box with height: 100% also becomes 680px tall

If you had two children inside .content with height: 50%, each would become 340px tall.

Real World Use Cases

Where this pattern is used

Dashboards

A dashboard may have:

  • a top navigation bar
  • a chart or data table below it

The chart area should fill the remaining height and scroll internally if needed.

Admin panels

Many admin tools use:

  • a header with account actions
  • a main working area below

This keeps the top controls visible while the main content grows and scrolls.

Chat applications

A chat app often has:

  • a header with room or user info
  • a message list filling the remaining space
  • sometimes nested panels inside the content area

Code editors and IDE-like layouts

Browser-based editors often need:

  • a toolbar at the top
  • editor panels filling the rest of the screen

Data tables

A page may need a filter bar on top and a table below that fills the rest of the viewport without making the entire page scroll.

Take Quiz

Real Codebase Usage

In real projects, developers usually combine this pattern with a few common layout habits.

1. Flex column shell

A common app shell looks like this:

.app {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.app-main {
  flex: 1;
  min-height: 0;
}

This creates a reliable full-height page structure.

2. Scroll only where needed

Instead of scrolling the whole page, developers often scroll just the content region:

.app-main {
  flex: 1;
  overflow: auto;
  min-height: 0;
}

This is useful for sticky headers, fixed toolbars, and split layouts.

3. Nested flex layouts

Inside the content area, developers often create another flex layout:

.content {
  display: flex;
  flex-direction: column;
}

.panel {
  flex: 1;
}

This is common for forms, tables, sidebars, and multi-panel screens.

4. Guarding percentage heights

If a child uses height: 100%, developers make sure every relevant parent has a defined height or is sized by flex/grid. Otherwise the percentage height may collapse or behave unexpectedly.

5. Avoiding table layout for page structure

Real codebases generally avoid tables for layout because:

  • they are meant for tabular data
  • they are less flexible than modern layout systems
  • they can make responsive design harder
  • they mix document meaning with visual layout

Common Mistakes

1. Using height: 100% without defining parent height

Broken example:

.content {
  height: 100%;
}

This does not work if the parent does not have a definite height.

Fix

Make the parent a full-height container or use Flexbox:

.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.content {
  flex: 1;
}

2. Forgetting to set html, body height

If you rely on percentage heights, this matters.

Broken example:

body {
  margin: 0;
}

.page {
  height: 100%;
}

Fix

html, body {
  height: 100%;
  margin: 0;
}

3. Expecting percentage child heights to work inside an auto-height parent

Broken example:

.content {
  background: #eee;
}

.child {
  height: 50%;
}

If .content has no defined height, .child cannot reliably use 50%.

Fix

Give .content a real height through flex sizing.

4. Forgetting min-height: 0 in flex layouts

A flex child may refuse to shrink and overflow instead of scrolling.

Fix

.content {
  flex: 1;
  min-height: 0;
  overflow: auto;
}

5. Using tables for non-tabular layout

Tables can appear to solve the height problem, but they are the wrong tool for general page layout.

Use tables for data, not for structuring the whole page.

6. Hard-coding header height unnecessarily

Broken approach:

.content {
  height: calc(100vh - 80px);
}

This only works if the header is always 80px tall.

Better approach

Let the header size naturally and let Flexbox fill the rest.

Comparisons

ApproachBest forHandles unknown header heightSupports remaining space wellNotes
table layoutOld layoutsYesYesWorks, but not recommended for page layout
height: 100% onlySimple casesNoWeakRequires defined heights on all parents
calc(100vh - 80px)Fixed-height headerNoGoodBreaks if header height changes
FlexboxModern app layoutsYesExcellentBest fit for header + remaining content
CSS GridMore complex 2D layoutsYesExcellentGreat when rows and columns are both important

Flexbox vs calc()

.content {
  height: calc(100vh - 80px);
}

This is fine only when the header height is known and fixed.

.page {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.content {
  flex: 1;
}

This works when the header height is dynamic.

Flexbox vs CSS Grid

Both can solve this.

Flexbox

Better when the layout is mainly one-dimensional: a vertical stack of header and content.

Grid

Useful if you also need columns or more complex row/column control.

Example grid version:

.page {
  display: grid;
  grid-template-rows: auto 1fr;
  height: 100vh;
}

This means:

  • first row: natural header height
  • second row: all remaining space
Take Quiz

Cheat Sheet

html, body {
  height: 100%;
  margin: 0;
}

.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.header {
  /* natural height */
}

.content {
  flex: 1;
  min-height: 0;
  overflow: auto;
}

Rules to remember

  • height: 100% needs a parent with a defined height.
  • flex: 1 makes an element fill remaining space.
  • Use min-height: 0 on flex children that should shrink and scroll.
  • Use tables for tabular data, not page layout.
  • Use 100vh when you want viewport height.
  • If child elements use percentage heights, the parent must have a real computed height.

Useful alternatives

Flexbox

.page {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

Grid

.page {
  display: grid;
  grid-template-rows: auto 1fr;
  height: 100vh;
}

Fixed header only

.content {
  height: calc(100vh - 80px);
}

Use this only if the header height is known.

Common debugging checks

  • Did you set html, body { height: 100%; } if using % heights?
  • Does the parent actually have a defined height?
  • Is a flex child missing min-height: 0?
  • Are you trying to use % height inside an auto-sized container?

FAQ

How do I make a div take the rest of the page height?

Use a parent container with display: flex, flex-direction: column, and give the content area flex: 1.

Why does height: 100% not work in my div?

Because percentage height only works when the parent has a defined height. If the parent height is auto, the child cannot reliably fill it.

Can I do this without knowing the header height?

Yes. Flexbox and Grid both work well when the header has dynamic height.

Is using a table for page layout bad?

It is outdated for general layout. Tables are intended for tabular data, not app page structure.

What if I want only the content area to scroll?

Set overflow: auto on the content area and keep the overall page container at viewport height.

Can children inside the content area use height: 50% or height: 100%?

Yes, as long as the content area has a definite height, which Flexbox can provide.

Should I use Flexbox or Grid for this layout?

Use Flexbox for a simple vertical header/content layout. Use Grid if the page also needs more complex rows and columns.

Take Quiz

Mini Project

Description

Build a simple app-style page with a variable-height header and a content area that fills the rest of the screen. Inside the content area, split the space into two equal sections using percentage heights. This demonstrates how to create a full-height layout without table-based markup.

Goal

Create a responsive page where the header keeps its natural height and the content area fills the remaining viewport height.

Requirements

  • Create a page container that fills the viewport height.
  • Add a header with natural, content-based height.
  • Make the main content area fill the remaining vertical space.
  • Inside the content area, add two panels that each take 50% of the content height.
  • Make the content area scroll if its content becomes too large.
Take Quiz

Keep learning

Related questions

View more