How can I make a div fill the remaining height of the screen after a header using CSS instead of tables?
I’m working on a web application where I want the content area to fill the entire screen height. The page has a header with a logo and account information, which can be of arbitrary height. I need the content div to fill the remaining space to the bottom of the screen.
Currently, I’m using a table-based layout:
CSS:
#page {
height: 100%;
width: 100%
}
#tdcontent {
height: 100%;
}
#content {
overflow: auto; /* or overflow: hidden; */
}
HTML:
<table id="page">
<tr>
<td id="tdheader">
<div id="header">...</div>
</td>
</tr>
<tr>
<td id="tdcontent">
<div id="content">...</div>
</td>
</tr>
</table>
This approach fills the entire page height without scrolling. However, I want to avoid using tables for layout.
Additional requirements:
- Elements inside the content div need to support percentage heights
- For example, if the header takes up 20% of screen height, a table at 50% inside #content should take up 40% of screen space
- The solution should allow nested elements to properly calculate their heights relative to the content area
What CSS techniques can achieve this layout without using tables?
To make a div fill the remaining height of the screen after a header using CSS instead of tables, you can use several modern CSS layout techniques. The most effective approaches use CSS Flexbox, CSS Grid, or viewport units combined with absolute positioning.
Contents:
- Using CSS Flexbox
- Using CSS Grid
- Using Viewport Units and Absolute Positioning
- Using CSS Table Display Properties
- Comparing the Methods
- Practical Implementation Example
Using CSS Flexbox
Flexbox is the most modern and recommended approach for this layout requirement. Set the body or parent container to display: flex with flex-direction: column, then allow the content area to grow and fill available space.
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.page-container {
display: flex;
flex-direction: column;
height: 100vh;
}
#header {
/* Header styles - height can be fixed or auto */
background: #f0f0f0;
padding: 20px;
}
#content {
flex: 1; /* This makes the content area grow to fill remaining space */
overflow: auto;
/* Nested elements with percentage heights will work correctly */
}
<div class="page-container">
<div id="header">...</div>
<div id="content">
<!-- Elements with percentage heights will work -->
<div style="height: 50%;">This will be 50% of content area</div>
</div>
</div>
Using CSS Grid
CSS Grid provides another elegant solution with similar results to Flexbox but with different syntax and capabilities.
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.page-container {
display: grid;
grid-template-rows: auto 1fr;
height: 100vh;
}
#header {
/* Header styles */
background: #f0f0f0;
padding: 20px;
}
#content {
/* Grid automatically handles the remaining space */
overflow: auto;
}
<div class="page-container">
<div id="header">...</div>
<div id="content">
<div style="height: 50%;">This will be 50% of content area</div>
</div>
</div>
Using Viewport Units and Absolute Positioning
For older browser support or when you need more precise control, you can use viewport units with absolute positioning:
html, body {
height: 100%;
margin: 0;
padding: 0;
position: relative;
}
#header {
/* Header styles */
background: #f0f0f0;
padding: 20px;
}
#content {
position: absolute;
top: [header-height];
left: 0;
right: 0;
bottom: 0;
overflow: auto;
}
To handle dynamic header heights, you can use CSS calc():
#content {
position: absolute;
top: calc([header-height] + [any-margin-padding]);
left: 0;
right: 0;
bottom: 0;
overflow: auto;
}
Using CSS Table Display Properties
If you want to maintain the semantic benefits of divs but use table-like layout behavior:
.page-container {
display: table;
width: 100%;
height: 100vh;
}
#header {
display: table-row;
height: auto;
}
#header > div {
display: table-cell;
}
#content {
display: table-row;
height: 1fr;
}
#content > div {
display: table-cell;
height: 100%;
overflow: auto;
}
Comparing the Methods
Here’s a comparison of the different approaches:
| Method | Browser Support | Flexibility | Performance | Recommendation |
|---|---|---|---|---|
| Flexbox | Excellent (IE11+) | High | Excellent | Best choice for modern sites |
| CSS Grid | Excellent (IE11 with -ms-) | Very High | Excellent | Best choice for complex layouts |
| Viewport + Absolute | Good | Medium | Good | Good for older browsers |
| CSS Table | Excellent | Medium | Good | Transitional from table layout |
Flexbox is generally the preferred method for this specific use case due to its simplicity and excellent browser support.
Practical Implementation Example
Here’s a complete working example using Flexbox:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Full Height Layout</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
font-family: Arial, sans-serif;
}
.page-container {
display: flex;
flex-direction: column;
height: 100vh;
}
#header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
#header h1 {
margin: 0;
font-size: 24px;
}
#content {
flex: 1; /* This makes the content area grow to fill remaining space */
overflow: auto;
padding: 20px;
background: #f8f9fa;
}
.nested-container {
height: 50%;
background: #e9ecef;
border: 2px solid #dee2e6;
padding: 20px;
margin-bottom: 20px;
}
.example {
height: 30%;
background: #fff;
border: 1px solid #ced4da;
padding: 15px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="page-container">
<div id="header">
<h1>Website Header</h1>
<p>Account information and navigation</p>
</div>
<div id="content">
<h2>Content Area</h2>
<p>This content area fills the remaining screen height.</p>
<div class="nested-container">
<h3>50% Height Container</h3>
<p>This element takes 50% of the content area height.</p>
<div class="example">30% Height Example</div>
<div class="example">Another 30% Height Example</div>
</div>
<div class="example">Standalone 30% Height Example</div>
</div>
</div>
</body>
</html>
This Flexbox-based solution meets all your requirements:
- The header can be any height (auto or fixed)
- The content div fills the remaining space to the bottom
- Nested elements with percentage heights work correctly
- No tables are used for layout
- The solution is modern, maintainable, and works across all modern browsers
For the best results, use the Flexbox approach as it provides the most flexible and maintainable solution for full-height layouts in modern web development.
Sources
- MDN Web Docs - Using CSS flexbox
- CSS-Tricks - Complete Guide to Flexbox
- MDN Web Docs - CSS Grid Layout
- Can I Use - Flexbox Support
- W3C CSS Flexbox Layout Module
Conclusion
To create a full-height layout without tables, CSS Flexbox is the most effective solution. By setting display: flex with flex-direction: column on the parent container and using flex: 1 on the content area, you can achieve the exact layout behavior you need. This approach maintains the semantic structure of your HTML while providing excellent browser support and allowing nested percentage heights to work correctly. For more complex layouts, CSS Grid offers similar capabilities with different syntax. Both methods are superior to table-based layouts in terms of maintainability, accessibility, and modern web standards.