Reputation: 34649
I am working on a web application where I want the content to fill the height of the entire screen.
The page has a header, which contains a logo, and account information. This could be an arbitrary height. I want the content div to fill the rest of the page to the bottom.
I have a header div
and a content div
. At the moment I am using a table for the layout like so:
CSS and HTML
#page {
height: 100%;
width: 100%
}
#tdcontent {
height: 100%;
}
#content {
overflow: auto; /* or overflow: hidden; */
}
<table id="page">
<tr>
<td id="tdheader">
<div id="header">...</div>
</td>
</tr>
<tr>
<td id="tdcontent">
<div id="content">...</div>
</td>
</tr>
</table>
The entire height of the page is filled, and no scrolling is required.
For anything inside the content div, setting top: 0;
will put it right underneath the header. Sometimes the content will be a real table, with its height set to 100%. Putting header
inside content
will not allow this to work.
Is there a way to achieve the same effect without using the table
?
Update:
Elements inside the content div
will have heights set to percentages as well. So something at 100% inside the div
will fill it to the bottom. As will two elements at 50%.
Update 2:
For instance, if the header takes up 20% of the screen's height, a table specified at 50% inside #content
would take up 40% of the screen space. So far, wrapping the entire thing in a table is the only thing that works.
Upvotes: 2822
Views: 1972208
Reputation: 726
For me the easiest way to do this is by using Grid. But, I am looking for an easier approach. Here is How I am doing it and it works. But, it becomes too much of pain if we have a lot of nested divs.
<div style={{ display:grid, gridTemplateRows: 'max-content 1fr', }}>
<div>
Header
</div>
<div style={{height: '100%',minHeight: '0'}}>
Content
</div>
</div>
Upvotes: 4
Reputation: 367
Try this way:
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
.first-div {
height: 20vh; // this height can be any length
}
.second-div {
flex: 1; // fills up the remaining space on the screen
}
<div class='container'>
<div class='first-div'>
...
</div>
<div class='second-div'>
...
</div>
</div>
Upvotes: 13
Reputation: 47
max-height: -webkit-fill-available;
that's it. all you need.
On Safari you may notice that the height being incorrect when you have height of 100vh because the toolbar messes with the browser height. More information and other techniques to solve this can be found in this article https://lukechannings.com/blog/2021-06-09-does-safari-15-fix-the-vh-bug/
Upvotes: -1
Reputation: 33
After calculating the pixels of your content, you can try to find it by subtracting it from 100vh under another label.##
.header {
height: 100px;
/* set the height of the header */
background-color: #ccc;
}
.content {
height: calc(100vh - 100px);
/* calculate the height of the content */
background-color: #eee;
}
<div class="header">Header content</div>
<div class="content">Content goes here</div>
Upvotes: -4
Reputation: 84
My method makes use of calc()
function in CSS. It calculates the space remaining when an item of known size is on the page.
#fixed-size {
height: 2rem;
background-color: red;
}
#fill-remaining {
background-color: blue;
height: calc(100vh - 2rem);
}
<div>
<div id="fixed-size">Known Size</div>
<div id="fill-remaining">Fill Remaining</div>
</div>
Upvotes: 1
Reputation: 744
A nice hack would be to set the css margin property to "auto". It will make the div take up all the remaining height & width .
The downside is that it would be computed as margin and not the content .
See attached screenshots:
Upvotes: 3
Reputation: 15915
If you can deal with not supporting old browsers (that is, MSIE 9 or older), you can do this with Flexible Box Layout Module which is already W3C CR. That module allows other nice tricks, too, such as re-ordering content.
Unfortunately, MSIE 9 or lesser do not support this and you have to use vendor prefix for the CSS property for every browser other than Firefox. Hopefully other vendors drop the prefix soon, too.
An another choice would be CSS Grid Layout but that has even less support from stable versions of browsers. In practice, only MSIE 10 supports this.
Update year 2020: All modern browsers support both display: flex
and display: grid
. The only one missing is support for subgrid
which in only supported by Firefox. Note that MSIE does not support either by the spec but if you're willing to add MSIE specific CSS hacks, it can be made to behave. I would suggest simply ignoring MSIE because even Microsoft says it should not be used anymore. Microsoft Edge supports these features just fine (except for subgrid support since is shares the Blink rendering engine with Chrome).
Example using display: grid
:
html, body
{
min-height: 100vh;
padding: 0;
margin: 0;
}
body
{
display: grid;
grid:
"myheader" auto
"mymain" minmax(0,1fr)
"myfooter" auto /
minmax(10rem, 90rem);
}
header
{
grid-area: myheader;
background: yellow;
}
main
{
grid-area: mymain;
background: pink;
align-self: center
/* or stretch
+ display: flex;
+ flex-direction: column;
+ justify-content: center; */
}
footer
{
grid-area: myfooter;
background: cyan;
}
<header>Header content</header>
<main>Main content which should be centered and the content length may change.
<details><summary>Collapsible content</summary>
<p>Here's some text to cause more vertical space to be used.</p>
<p>Here's some text to cause more vertical space to be used (2).</p>
<p>Here's some text to cause more vertical space to be used (3).</p>
<p>Here's some text to cause more vertical space to be used (4).</p>
<p>Here's some text to cause more vertical space to be used (5).</p>
</details>
</main>
<footer>Footer content</footer>
Example using display: flex
:
html, body
{
min-height: 100vh;
padding: 0;
margin: 0;
}
body
{
display: flex;
}
main
{
background: pink;
align-self: center;
}
<main>Main content which should be centered and the content length may change.
<details><summary>Collapsible content</summary>
<p>Here's some text to cause more vertical space to be used.</p>
<p>Here's some text to cause more vertical space to be used (2).</p>
<p>Here's some text to cause more vertical space to be used (3).</p>
<p>Here's some text to cause more vertical space to be used (4).</p>
<p>Here's some text to cause more vertical space to be used (5).</p>
</details>
</main>
Upvotes: 29
Reputation: 9279
Some of my components were loaded dynamically, and this caused me problems with setting the height of the navigation bar.
What I did was to use the ResizeObserver API.
function observeMainResize(){
const resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) {
$("nav").height(Math.max($("main").height(),
$("nav") .height()));
}
});
resizeObserver.observe(document.querySelector('main'));
}
then:
...
<body onload="observeMainResize()">
<nav>...</nav>
<main>...</main>
...
Upvotes: 0
Reputation: 1855
For mobile app i use only VH and VW
<div class="container">
<div class="title">Title</div>
<div class="content">Content</div>
<div class="footer">Footer</div>
</div>
.container {
width: 100vw;
height: 100vh;
font-size: 5vh;
}
.title {
height: 20vh;
background-color: red;
}
.content {
height: 60vh;
background: blue;
}
.footer {
height: 20vh;
background: green;
}
Demo - https://jsfiddle.net/u763ck92/
Upvotes: 7
Reputation: 1065
In Bootstrap:
CSS Styles:
html, body {
height: 100%;
}
1) Just fill the height of the remaining screen space:
<body class="d-flex flex-column">
<div class="d-flex flex-column flex-grow-1">
<header>Header</header>
<div>Content</div>
<footer class="mt-auto">Footer</footer>
</div>
</body>
2) fill the height of the remaining screen space and aligning content to the middle of the parent element:
<body class="d-flex flex-column">
<div class="d-flex flex-column flex-grow-1">
<header>Header</header>
<div class="d-flex flex-column flex-grow-1 justify-content-center">Content</div>
<footer class="mt-auto">Footer</footer>
</div>
</body>
Upvotes: 29
Reputation: 8526
All you have to do if you're using display: flex on the parent div is to simply set height to stretch or fill like so
.divName {
height: stretch
}
Upvotes: -3
Reputation: 16680
Here is an answer that uses grids.
.the-container-div {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto min-content;
height: 100vh;
}
.view-to-remain-small {
grid-row: 2;
}
.view-to-be-stretched {
grid-row: 1
}
Upvotes: 4
Reputation: 418
This is my own minimal version of Pebbl's solution. Took forever to find the trick to get it to work in IE11. (Also tested in Chrome, Firefox, Edge, and Safari.)
html {
height: 100%;
}
body {
height: 100%;
margin: 0;
}
section {
display: flex;
flex-direction: column;
height: 100%;
}
div:first-child {
background: gold;
}
div:last-child {
background: plum;
flex-grow: 1;
}
<body>
<section>
<div>FIT</div>
<div>GROW</div>
</section>
</body>
Upvotes: 17
Reputation:
One more solution using CSS Grid
Define grid
.root {
display: grid;
grid-template-rows: minmax(60px, auto) minmax(0, 100%);
}
First row(header): Min height can be set-up and max height will depend on content. Second row(content) will try to fit free space that left after header.
The advantage of this approach is content can be scrolled independently of header, so header is always at the top of the page
body, html {
margin: 0;
height: 100%;
}
.root {
display: grid;
grid-template-rows: minmax(60px, auto) minmax(0, 100%);
height: 100%;
}
.header {
background-color: lightblue;
}
button {
background-color: darkslateblue;
color: white;
padding: 10px 50px;
margin: 10px 30px;
border-radius: 15px;
border: none;
}
.content {
background-color: antiquewhite;
overflow: auto;
}
.block {
width: calc(100% - 20px);
height: 120px;
border: solid aquamarine;
margin: 10px;
}
<div class="root">
<div class="header">
<button>click</button>
<button>click</button>
<button>click</button>
<button>click</button>
<button>click</button>
</div>
<div class="content">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
<div class="footer"></div>
</div>
Upvotes: 4
Reputation: 35995
There are two other answers briefly mentioning flexbox; however, that was more than two years ago, and they don't provide any examples. The specification for flexbox has definitely settled now.
Note: Though CSS Flexible Boxes Layout specification is at the Candidate Recommendation stage, not all browsers have implemented it. WebKit implementation must be prefixed with -webkit-; Internet Explorer implements an old version of the spec, prefixed with -ms-; Opera 12.10 implements the latest version of the spec, unprefixed. See the compatibility table on each property for an up-to-date compatibility status.
(taken from https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes)
All major browsers and IE11+ support Flexbox. For IE 10 or older, you can use the FlexieJS shim.
To check current support you can also see here: http://caniuse.com/#feat=flexbox
With flexbox you can easily switch between any of your rows or columns either having fixed dimensions, content-sized dimensions or remaining-space dimensions. In my example I have set the header to snap to its content (as per the OPs question), I've added a footer to show how to add a fixed-height region and then set the content area to fill up the remaining space.
html,
body {
height: 100%;
margin: 0;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
}
.box .row {
border: 1px dotted grey;
}
.box .row.header {
flex: 0 1 auto;
/* The above is shorthand for:
flex-grow: 0,
flex-shrink: 1,
flex-basis: auto
*/
}
.box .row.content {
flex: 1 1 auto;
}
.box .row.footer {
flex: 0 1 40px;
}
<!-- Obviously, you could use HTML5 tags like `header`, `footer` and `section` -->
<div class="box">
<div class="row header">
<p><b>header</b>
<br />
<br />(sized to content)</p>
</div>
<div class="row content">
<p>
<b>content</b>
(fills remaining space)
</p>
</div>
<div class="row footer">
<p><b>footer</b> (fixed height)</p>
</div>
</div>
In the CSS above, the flex property shorthands the flex-grow, flex-shrink, and flex-basis properties to establish the flexibility of the flex items. Mozilla has a good introduction to the flexible boxes model.
Upvotes: 1759
Reputation: 157274
When you want the middle element to span across entire page vertically, you can use calc()
which is introduced in CSS3.
Assuming we have a fixed height header
and footer
elements and we want the section
tag to take entire available vertical height...
Assumed markup and your CSS should be
html,
body {
height: 100%;
}
header {
height: 100px;
background: grey;
}
section {
height: calc(100% - (100px + 150px));
/* Adding 100px of header and 150px of footer */
background: tomato;
}
footer {
height: 150px;
background-color: blue;
}
<header>100px</header>
<section>Expand me for remaining space</section>
<footer>150px</footer>
So here, what am doing is, adding up the height of elements and than deducting from 100%
using calc()
function.
Just make sure that you use height: 100%;
for the parent elements.
Upvotes: 139
Reputation: 6680
None of the solutions posted work when you need the bottom div to scroll when the content is too tall. Here's a solution that works in that case:
.table {
display: table;
}
.table-row {
display: table-row;
}
.table-cell {
display: table-cell;
}
.container {
width: 400px;
height: 300px;
}
.header {
background: cyan;
}
.body {
background: yellow;
height: 100%;
}
.body-content-outer-wrapper {
height: 100%;
}
.body-content-inner-wrapper {
height: 100%;
position: relative;
overflow: auto;
}
.body-content {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
<div class="table container">
<div class="table-row header">
<div>This is the header whose height is unknown</div>
<div>This is the header whose height is unknown</div>
<div>This is the header whose height is unknown</div>
</div>
<div class="table-row body">
<div class="table-cell body-content-outer-wrapper">
<div class="body-content-inner-wrapper">
<div class="body-content">
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
<div>This is the scrollable content whose height is unknown</div>
</div>
</div>
</div>
</div>
</div>
Original source: Filling the Remaining Height of a Container While Handling Overflow in CSS
Upvotes: 46
Reputation: 3013
It could be done purely by CSS
using vh
:
#page {
display:block;
width:100%;
height:95vh !important;
overflow:hidden;
}
#tdcontent {
float:left;
width:100%;
display:block;
}
#content {
float:left;
width:100%;
height:100%;
display:block;
overflow:scroll;
}
and the HTML
<div id="page">
<div id="tdcontent"></div>
<div id="content"></div>
</div>
I checked it, It works in all major browsers: Chrome
, IE
, and FireFox
Upvotes: 37
Reputation: 7872
A simple solution, using flexbox:
html,
body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
}
.content {
flex-grow: 1;
}
<body>
<div>header</div>
<div class="content"></div>
</body>
An alternate solution, with a div centered within the content div
Upvotes: 113
Reputation: 726
There's a ton of answers now, but I found using height: 100vh;
to work on the div element that needs to fill up the entire vertical space available.
In this way, I do not need to play around with display or positioning. This came in handy when using Bootstrap to make a dashboard wherein I had a sidebar and a main. I wanted the main to stretch and fill the entire vertical space so that I could apply a background colour.
div {
height: 100vh;
}
Supports IE9 and up: click to see the link
Upvotes: 22
Reputation: 104640
How about you simply use vh
which stands for view height
in CSS...
Look at the code snippet I created for you below and run it:
body {
padding: 0;
margin: 0;
}
.full-height {
width: 100px;
height: 100vh;
background: red;
}
<div class="full-height">
</div>
Also, look at the image below which I created for you:
Upvotes: 50
Reputation: 9544
style="height:100vh"
solved the problem for me. In my case I applied this to the required div
Upvotes: 10
Reputation: 9110
CSS3 Simple Way
height: calc(100% - 10px); // 10px is height of your first div...
all major browsers these days support it, so go ahead if you don't have requirement to support vintage browsers.
Upvotes: 41
Reputation: 6023
The original post is more than 3 years ago. I guess many people who come to this post like me are looking for an app-like layout solution, say a somehow fixed header, footer, and full height content taking up the rest screen. If so, this post may help, it works on IE7+, etc.
http://blog.stevensanderson.com/2011/10/05/full-height-app-layouts-a-css-trick-to-make-it-easier/
And here are some snippets from that post:
@media screen {
/* start of screen rules. */
/* Generic pane rules */
body { margin: 0 }
.row, .col { overflow: hidden; position: absolute; }
.row { left: 0; right: 0; }
.col { top: 0; bottom: 0; }
.scroll-x { overflow-x: auto; }
.scroll-y { overflow-y: auto; }
.header.row { height: 75px; top: 0; }
.body.row { top: 75px; bottom: 50px; }
.footer.row { height: 50px; bottom: 0; }
/* end of screen rules. */
}
<div class="header row" style="background:yellow;">
<h2>My header</h2>
</div>
<div class="body row scroll-y" style="background:lightblue;">
<p>The body</p>
</div>
<div class="footer row" style="background:#e9e9e9;">
My footer
</div>
Upvotes: 197
Reputation: 10627
I've been searching for an answer for this as well. If you are fortunate enough to be able to target IE8 and up, you can use display:table
and related values to get the rendering rules of tables with block-level elements including div.
If you are even luckier and your users are using top-tier browsers (for example, if this is an intranet app on computers you control, like my latest project is), you can use the new Flexible Box Layout in CSS3!
Upvotes: 29
Reputation: 6036
Spinning off the idea of Mr. Alien...
This seems a cleaner solution than the popular flex box one for CSS3 enabled browsers.
Simply use min-height(instead of height) with calc() to the content block.
The calc() starts with 100% and subtracts heights of headers and footers (need to include padding values)
Using "min-height" instead of "height" is particularly useful so it can work with javascript rendered content and JS frameworks like Angular2. Otherwise, the calculation will not push the footer to the bottom of the page once the javascript rendered content is visible.
Here is a simple example of a header and footer using 50px height and 20px padding for both.
Html:
<body>
<header></header>
<div class="content"></div>
<footer></footer>
</body>
Css:
.content {
min-height: calc(100% - (50px + 20px + 20px + 50px + 20px + 20px));
}
Of course, the math can be simplified but you get the idea...
Upvotes: 5
Reputation: 114978
Just defining the body
with display:grid
and the grid-template-rows
using auto
and the fr
value property.
* {
margin: 0;
padding: 0;
}
html {
height: 100%;
}
body {
min-height: 100%;
display: grid;
grid-template-rows: auto 1fr auto;
}
header {
padding: 1em;
background: pink;
}
main {
padding: 1em;
background: lightblue;
}
footer {
padding: 2em;
background: lightgreen;
}
main:hover {
height: 2000px;
/* demos expansion of center element */
}
<header>HEADER</header>
<main>MAIN</main>
<footer>FOOTER</footer>
A Complete Guide to Grids @ CSS-Tricks.com
Upvotes: 19
Reputation: 1416
It's dynamic calc the remining screen space, better using Javascript.
You can use CSS-IN-JS technology, like below lib:
https://github.com/cssobj/cssobj
DEMO: https://cssobj.github.io/cssobj-demo/
Upvotes: 0
Reputation: 63450
I had the same problem but I could not make work the solution with flexboxes above. So I created my own template, that includes:
I used flexboxes but in a more simple way, using only properties display: flex and flex-direction: row|column:
I do use angular and I want my component sizes to be 100% of their parent element.
The key is to set the size (in percents) for all parents inorder to limit their size. In the following example myapp height has 100% of the viewport.
The main component has 90% of the viewport, because header and footer have 5%.
I posted my template here: https://jsfiddle.net/abreneliere/mrjh6y2e/3
body{
margin: 0;
color: white;
height: 100%;
}
div#myapp
{
display: flex;
flex-direction: column;
background-color: red; /* <-- painful color for your eyes ! */
height: 100%; /* <-- if you remove this line, myapp has no limited height */
}
div#main /* parent div for sidebar and content */
{
display: flex;
width: 100%;
height: 90%;
}
div#header {
background-color: #333;
height: 5%;
}
div#footer {
background-color: #222;
height: 5%;
}
div#sidebar {
background-color: #666;
width: 20%;
overflow-y: auto;
}
div#content {
background-color: #888;
width: 80%;
overflow-y: auto;
}
div.fized_size_element {
background-color: #AAA;
display: block;
width: 100px;
height: 50px;
margin: 5px;
}
Html:
<body>
<div id="myapp">
<div id="header">
HEADER
<div class="fized_size_element"></div>
</div>
<div id="main">
<div id="sidebar">
SIDEBAR
<div class="fized_size_element"></div>
<div class="fized_size_element"></div>
<div class="fized_size_element"></div>
<div class="fized_size_element"></div>
<div class="fized_size_element"></div>
<div class="fized_size_element"></div>
<div class="fized_size_element"></div>
<div class="fized_size_element"></div>
</div>
<div id="content">
CONTENT
</div>
</div>
<div id="footer">
FOOTER
</div>
</div>
</body>
Upvotes: 5