HTML/CSS - Sidebar Length 100% Page Height, Regardless of Vertical Scrollbar - html

I'm sure this has been asked quite some times however after quite some time searching for a solution I have finally resorted to asking a question here!
I am working on an HTML Help file for an application I am developing, where the file is split into two sections. One, a sidebar (floated to the left) and two, the main content section (also floating left).
The problem I am facing is that when the main content extends beyond 100% of the page height, the sidebar background stops.
I would use the faux column effect where I assign the a background image of my sidebar however to maintain my design's integrity I have to set a different background image for the body.
Check out this JS Fiddle I set up - http://jsfiddle.net/5gpFx/
Hopefully that can help you see what the issue is if I failed to communicate it well enough!
Cheers!

Just wrap both columns in a container and set the faux-column background on that - this way the body will be available for setting whatever image you want. I've made a simple example here: http://jsfiddle.net/5gpFx/2/

I had the same problem but I could not make work the solution with flexboxes above. So I created my own template, that includes:
a header with a fixed size element
a footer
a side bar with a scrollbar that occupies the remaining height
content
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>

Related

Place div to bottom of parent div [duplicate]

Given the following HTML:
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
</div>
I would like #copyright to stick to the bottom of #container. Can I achieve this without using absolute positioning?
Likely not.
Assign position:relative to #container, and then position:absolute; bottom:0; to #copyright.
#container {
position: relative;
}
#copyright {
position: absolute;
bottom: 0;
}
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
</div>
Actually, the accepted answer by #User will only work if the window is tall and the content is short. But if the content is tall and the window is short, it will put the copyright info over the page content, and then scrolling down to see the content will leave you with a floating copyright notice. That makes this solution useless for most pages (like this page, actually).
The most common way of doing this is the "CSS sticky footer" approach demonstrated, or a slightly slimmer variation. This approach works great -- IF you have a fixed height footer.
If you need a variable height footer that will appear at the bottom of the window if the content is too short, and at the bottom of the content if the window is too short, what do you do?
Swallow your pride and use a table.
For example:
* {
padding: 0;
margin: 0;
}
html, body {
height: 100%;
}
#container {
height: 100%;
border-collapse: collapse;
}
<!DOCTYPE html>
<html>
<body>
<table id="container">
<tr>
<td valign="top">
<div id="main">Lorem ipsum, etc.</div>
</td>
</tr>
<tr>
<td valign="bottom">
<div id="footer">Copyright some evil company...</div>
</td>
</tr>
</table>
</body>
</html>
Try it out. This will work for any window size, for any amount of content, for any size footer, on every browser... even IE6.
If you're cringing at the thought of using a table for layout, take a second to ask yourself why. CSS was supposed to make our lives easier -- and it has, overall -- but the fact is that even after all these years, it's still a broken, counter-intuitive mess. It can't solve every problem. It's incomplete.
Tables aren't cool, but at least for now, they are sometimes the best way to solve a design problem.
The flexbox approach!
In supported browsers, you can use the following:
Example Here
.parent {
display: flex;
flex-direction: column;
}
.child {
margin-top: auto;
}
.parent {
height: 100px;
border: 5px solid #000;
display: flex;
flex-direction: column;
}
.child {
height: 40px;
width: 100%;
background: #f00;
margin-top: auto;
}
<div class="parent">
<div class="child">Align to the bottom</div>
</div>
The solution above is probably more flexible, however, here is an alternative solution:
Example Here
.parent {
display: flex;
}
.child {
align-self: flex-end;
}
.parent {
height: 100px;
border: 5px solid #000;
display: flex;
}
.child {
height: 40px;
width: 100%;
background: #f00;
align-self: flex-end;
}
<div class="parent">
<div class="child">Align to the bottom</div>
</div>
As a side note, you may want to add vendor prefixes for additional support.
Yes you can do this without absolute positioning and without using tables (which screw with markup and such).
DEMO
This is tested to work on IE>7, chrome, FF & is a really easy thing to add to your existing layout.
<div id="container">
Some content you don't want affected by the "bottom floating" div
<div>supports not just text</div>
<div class="foot">
Some other content you want kept to the bottom
<div>this is in a div</div>
</div>
</div>
#container {
height:100%;
border-collapse:collapse;
display : table;
}
.foot {
display : table-row;
vertical-align : bottom;
height : 1px;
}
It effectively does what float:bottom would, even accounting for the issue pointed out in #Rick Reilly's answer!
Pure CSS, without absolute positioning, without fixing any height, cross-browser (IE9+)
check out that Working Fiddle
Because normal flow is 'top-to-bottom' we can't simply ask the #copyright div to stick to the bottom of his parent without absolutely positioning of some sort, But if we wanted the #copyright div to stick to the top of his parent, it will be very simple - because this is the normal flow way.
So we will use this in our advantage.
we will change the order of the divs in the HTML, now the #copyright div is at the top, and the content follow it right away.
we also make the content div stretch all the way (using pseudo elements and clearing techniques)
now it's just a matter of inverting that order back in the view. that can be easily done with CSS transform.
We rotate the container by 180deg, and now: up-is-down. (and we inverse back the content to look normal again)
If we want to have a scroolbar within the content area, we need to apply a little bit more of CSS magic. as can be showed Here [in that example, the content is below a header - but its the same idea]
* {
margin: 0;
padding: 0;
}
html,
body,
#Container {
height: 100%;
color: white;
}
#Container:before {
content: '';
height: 100%;
float: left;
}
#Copyright {
background-color: green;
}
#Stretch {
background-color: blue;
}
#Stretch:after {
content: '';
display: block;
clear: both;
}
#Container,
#Container>div {
-moz-transform: rotateX(180deg);
-ms-transform: rotateX(180deg);
-o-transform: rotate(180deg);
-webkit-transform: rotateX(180deg);
transform: rotateX(180deg);
}
<div id="Container">
<div id="Copyright">
Copyright Foo web designs
</div>
<div id="Stretch">
<!-- Other elements here -->
<div>Element 1</div>
<div>Element 2</div>
</div>
</div>
CSS Grid
Since the usage of CSS Grid is increasing, I would like to suggest align-self to the element that is inside a grid container.
align-self can contain any of the values: end, self-end, flex-end for the following example.
#parent {
display: grid;
}
#child1 {
align-self: end;
}
/* Extra Styling for Snippet */
#parent {
height: 150px;
background: #5548B0;
color: #fff;
padding: 10px;
font-family: sans-serif;
}
#child1 {
height: 50px;
width: 50px;
background: #6A67CE;
text-align: center;
vertical-align: middle;
line-height: 50px;
}
<div id="parent">
<!-- Other elements here -->
<div id="child1">
1
</div>
</div>
Create another container div for the elements above #copyright. Just above copyright add a new div:
<div style="clear:both;"></div>
It will force the footer to be under everything else, just like in the case of using relative positioning (bottom:0px;).
Try this;
<div id="container">
<div style="height: 100%; border:1px solid #ff0000;">
<!-- Other elements here -->
</div>
</div>
<div id="copyright" style="position:relative;border:1px solid #00ff00;top:-25px">
Copyright Foo web designs
</div>
While none of the answers provided here seemed to apply or work in my particular case, I came across this article which provides this neat solution :
#container {
display: table;
}
#copyright {
display: table-footer-group;
}
I find it very useful for applying responsive design for mobile display without having to reorder all the html code of a website, setting body itself as a table.
Note that only the first table-footer-group or table-header-group will be rendered as such : if there are more than one, the others will be rendered as table-row-group.
You can indeed align the box to the bottom without using position:absolute if you know the height of the #container using the text alignment feature of inline-block elements.
Here you can see it in action.
This is the code:
#container {
/* So the #container most have a fixed height */
height: 300px;
line-height: 300px;
background:Red;
}
#container > * {
/* Restore Line height to Normal */
line-height: 1.2em;
}
#copyright {
display:inline-block;
vertical-align:bottom;
width:100%; /* Let it be a block */
background:green;
}
Using the translateY and top property
Just set element child to position: relative and than move it top: 100% (that's the 100% height of the parent) and stick to bottom of parent by transform: translateY(-100%) (that's -100% of the height of the child).
BenefitS
you do not take the element from the page flow
it is dynamic
But still just workaround :(
.copyright{
position: relative;
top: 100%;
transform: translateY(-100%);
}
Don't forget prefixes for the older browser.
CodePen link here.
html, body {
width: 100%;
height: 100%;
}
.overlay {
min-height: 100%;
position: relative;
}
.container {
width: 900px;
position: relative;
padding-bottom: 50px;
}
.height {
width: 900px;
height: 50px;
}
.footer {
width: 900px;
height: 50px;
position: absolute;
bottom: 0;
}
<div class="overlay">
<div class="container">
<div class="height">
content
</div>
</div>
<div class="footer">
footer
</div>
</div>
If you want it to "stick" to the bottom, regardless of the height of container, then absolute positioning is the way to go. Of course, if the copyright element is the last in the container it'll always be at the bottom anyway.
Can you expand on your question? Explain exactly what you're trying to do (and why you don't want to use absolute positioning)?
If you do not know the height of child block:
#parent {
background:green;
width:200px;
height:200px;
display:table-cell;
vertical-align:bottom;
}
.child {
background:red;
vertical-align:bottom;
}
<div id="parent">
<div class="child">child
</div>
</div>
http://jsbin.com/ULUXIFon/3/edit
If you know the height of the child block add the child block then add padding-top/margin-top:
#parent {
background:green;
width:200px;
height:130px;
padding-top:70px;
}
.child {
background:red;
vertical-align:
bottom;
height:130px;
}
<div id="parent">
<div class="child">child
</div>
</div>
You can use grid by assigning the available space to the content at the top:
#container {
display: grid;
grid-template-rows: 1fr auto;
height: 10rem; /* or 100% or anything */
}
<div id="container">
This is random content.
<div id="copyright">
Copyright Foo web designs
</div>
</div>
Also, if there's stipulations with using position:absolute; or position:relative;, you can always try padding parent div or putting a margin-top:x;. Not a very good method in most cases, but it may come in handy in some cases.
Solution for this specific scenario:
Place inner at the bottom of parent . The height of the parent is set by the height of its "tallest" sibling
The set up:
I have a row with multiple <div class="container">
These <div class="container"> are next to each other inside another <div class="supercontainer">
Each <div class="container"> has 3 inner divs on top of each other: <div class="title">, <div class="content">, <div class="footer">
The desired result:
All <div class="container"> have the same height. The height is not defined in px, it will be the height of the "tallest" among them.
<div class="title"> should be at the top of <div class="container">
<div class="content"> should be placed below <div class="title">
<div class="footer"> should be placed at the bottom of <div class="container"> without overlapping with the previous content
This is the current state: https://codepen.io/xavier-atero/pen/ExvWQww
.supercontainer {
border: solid 1px black;
display: flex;
}
.container, .other-container {
position: relative;
border: solid 1px red;
width: 200px;
margin: 10px;
}
.title {
margin: 10px;
border: solid 1px blue;
}
.content {
margin: 10px;
border: solid 1px cyan;
}
.footer {
margin: 10px;
background: lime;
}
<body>
<div class="supercontainer">
<div class="container">
<div class="title">
This part represents the title and it is placed on top
</div>
<div class="content">
This one represents the body and it is placed below the title
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
<div class="other-container">
<div class="title">
This part represents the title and it is placed on top.
</div>
<div class="content">
This one represents the body and it is placed below the title. This one is longer than the first one to stretch the parent div. Since it is longer, the footers of the two containers are not alinged.
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
</div>
</body>
__________ Solution with FLEXBOX __________
This is the outcome: https://codepen.io/xavier-atero/pen/MWvpBMz
.supercontainer {
border: solid 1px black;
display: flex;
}
.container, .other-container {
position: relative;
border: solid 1px red;
width: 200px;
margin: 10px;
display: flex;
flex-direction: column;
}
.title {
margin: 10px;
border: solid 1px blue;
}
.content {
margin: 10px;
border: solid 1px cyan;
}
.footer {
margin: 10px;
background: lime;
margin-top: auto;
border: solid 1px fuchsia;
}
<body>
<div class="supercontainer">
<div class="container">
<div class="title">
This part represents the title and it is placed on top
</div>
<div class="content">
This one represents the body and it is placed below the title
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
<div class="other-container">
<div class="title">
This part represents the title and it is placed on top.
</div>
<div class="content">
This one represents the body and it is placed below the title. This one is longer than the first one to stretch the parent div. Since it is longer, the footers of the two containers are not alinged.
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
</div>
</body>
__________ Solution with TABLE-ROW __________
This is the outcome: https://codepen.io/xavier-atero/pen/rNzyKJm
.supercontainer {
border: solid 1px black;
display: flex;
}
.container, .other-container {
position: relative;
border: solid 1px red;
width: 200px;
margin: 10px;
border-collapse:collapse;
display : table;
}
.title {
margin: 10px;
border: solid 1px blue;
}
.content {
margin: 10px;
border: solid 1px cyan;
}
.footer {
margin: 10px;
background: lime;
border: solid 1px fuchsia;
display: table-row;
vertical-align: bottom;
height: 1px;
}
<body>
<div class="supercontainer">
<div class="container">
<div class="title">
This part represents the title and it is placed on top
</div>
<div class="content">
This one represents the body and it is placed below the title
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
<div class="other-container">
<div class="title">
This part represents the title and it is placed on top.
</div>
<div class="content">
This one represents the body and it is placed below the title. This one is longer than the first one to stretch the parent div. Since it is longer, the footers of the two containers are not alinged.
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
</div>
</body>
#container{width:100%; float:left; position:relative;}
#copyright{position:absolute; bottom:0px; left:0px; background:#F00; width:100%;}
#container{background:gray; height:100px;}
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
</div>
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
</div>
Don't wanna use "position:absolute" for sticky footer at bottom. Then you can do this way:
html,
body {
height: 100%;
margin: 0;
}
.wrapper {
min-height: 100%;
/* Equal to height of footer */
/* But also accounting for potential margin-bottom of last child */
margin-bottom: -50px;
}
.footer{
background: #000;
text-align: center;
color: #fff;
}
.footer,
.push {
height: 50px;
}
<html>
<body>
<!--HTML Code-->
<div class="wrapper">
<div class="content">content</div>
<div class="push"></div>
</div>
<footer class="footer">test</footer>
</body>
</html>
Here is an approach targeted at making an element with a known height and width (at least approximately) float to the right and stay at the bottom, while behaving as an inline element to the other elements. It is focused at the bottom-right because you can place it easily in any other corner through other methods.
I needed to make a navigation bar which would have the actual links at the bottom right, and random sibling elements, while ensuring that the bar itself stretched properly, without disrupting the layout. I used a "shadow" element to occupy the navigation bar's links' space and added it at the end of the container's child nodes.
<!DOCTYPE html>
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
<span id="copyright-s">filler</span>
</div>
<style>
#copyright {
display:inline-block;
position:absolute;
bottom:0;
right:0;
}
#copyright-s {
float:right;
visibility:hidden;
width:20em; /* ~ #copyright.style.width */
height:3em; /* ~ #copyright.style.height */
}
</style>
Maybe this helps someone: You can always place the div outside the other div and then push it upwards using negative margin:
<div id="container" style="background-color: #ccc; padding-bottom: 30px;">
Hello!
</div>
<div id="copyright" style="margin-top: -20px;">
Copyright Foo web designs
</div>
Just because this hasn't been mentioned at all, what usually works well in situations like yours:
Placing the copyright-div after the container-div
You would only have to format the copyright-div in a similar way to the other container (same overall width, centering, etc.), and all is fine.
CSS:
#container, #copyright {
width: 1000px;
margin:0 auto;
}
HTML:
<div id="container">
<!-- Other elements here -->
</div>
<div id="copyright">
Copyright Foo web designs
</div>
The only time this might not be ideal is when your container-div is declared with height:100%, and the user would need to scroll down to see the copyright. But even still you could work around (e.g. margin-top:-20px - when the height of your copyright element is 20px).
No absolute positioning
No table layout
No crazy css, that looks different in every other browser (well IE at least, you know)
Simple and clear formatting
Aside: I know the OP asked for a solution that "... sticks to the bottom of the 'container' div ...", and not something under it, but come on, people are looking for good solutions here, and this is one!
There is nothing called float:bottom in CSS. The best way is using positioning in such cases:
position:absolute;
bottom:0;
For those only have one child in the container, you can use the table-cell and vertical-align approach which worked reliably for positioning a single div at the bottom of its parent.
Note that using table-footer-group as other answers mentioned will break the height calculation of parent table.
#container {
display: table;
width: 100%;
height: 200px;
}
#item {
display: table-cell;
vertical-align: bottom;
}
<div id="container">
<div id="item">Single bottom item</div>
</div>
According: w3schools.com
An element with position: absolute; is positioned relative to the
nearest positioned ancestor (instead of positioned relative to the
viewport, like fixed).
So you need to position the parent element with something either relative or absolute, etc and position the desired element to absolute and latter set bottom to 0.

Place inner <div> at the bottom of parent <div>. The height of the parent <div> is set by the height of its "tallest" sibling <div> [duplicate]

Given the following HTML:
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
</div>
I would like #copyright to stick to the bottom of #container. Can I achieve this without using absolute positioning?
Likely not.
Assign position:relative to #container, and then position:absolute; bottom:0; to #copyright.
#container {
position: relative;
}
#copyright {
position: absolute;
bottom: 0;
}
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
</div>
Actually, the accepted answer by #User will only work if the window is tall and the content is short. But if the content is tall and the window is short, it will put the copyright info over the page content, and then scrolling down to see the content will leave you with a floating copyright notice. That makes this solution useless for most pages (like this page, actually).
The most common way of doing this is the "CSS sticky footer" approach demonstrated, or a slightly slimmer variation. This approach works great -- IF you have a fixed height footer.
If you need a variable height footer that will appear at the bottom of the window if the content is too short, and at the bottom of the content if the window is too short, what do you do?
Swallow your pride and use a table.
For example:
* {
padding: 0;
margin: 0;
}
html, body {
height: 100%;
}
#container {
height: 100%;
border-collapse: collapse;
}
<!DOCTYPE html>
<html>
<body>
<table id="container">
<tr>
<td valign="top">
<div id="main">Lorem ipsum, etc.</div>
</td>
</tr>
<tr>
<td valign="bottom">
<div id="footer">Copyright some evil company...</div>
</td>
</tr>
</table>
</body>
</html>
Try it out. This will work for any window size, for any amount of content, for any size footer, on every browser... even IE6.
If you're cringing at the thought of using a table for layout, take a second to ask yourself why. CSS was supposed to make our lives easier -- and it has, overall -- but the fact is that even after all these years, it's still a broken, counter-intuitive mess. It can't solve every problem. It's incomplete.
Tables aren't cool, but at least for now, they are sometimes the best way to solve a design problem.
The flexbox approach!
In supported browsers, you can use the following:
Example Here
.parent {
display: flex;
flex-direction: column;
}
.child {
margin-top: auto;
}
.parent {
height: 100px;
border: 5px solid #000;
display: flex;
flex-direction: column;
}
.child {
height: 40px;
width: 100%;
background: #f00;
margin-top: auto;
}
<div class="parent">
<div class="child">Align to the bottom</div>
</div>
The solution above is probably more flexible, however, here is an alternative solution:
Example Here
.parent {
display: flex;
}
.child {
align-self: flex-end;
}
.parent {
height: 100px;
border: 5px solid #000;
display: flex;
}
.child {
height: 40px;
width: 100%;
background: #f00;
align-self: flex-end;
}
<div class="parent">
<div class="child">Align to the bottom</div>
</div>
As a side note, you may want to add vendor prefixes for additional support.
Yes you can do this without absolute positioning and without using tables (which screw with markup and such).
DEMO
This is tested to work on IE>7, chrome, FF & is a really easy thing to add to your existing layout.
<div id="container">
Some content you don't want affected by the "bottom floating" div
<div>supports not just text</div>
<div class="foot">
Some other content you want kept to the bottom
<div>this is in a div</div>
</div>
</div>
#container {
height:100%;
border-collapse:collapse;
display : table;
}
.foot {
display : table-row;
vertical-align : bottom;
height : 1px;
}
It effectively does what float:bottom would, even accounting for the issue pointed out in #Rick Reilly's answer!
Pure CSS, without absolute positioning, without fixing any height, cross-browser (IE9+)
check out that Working Fiddle
Because normal flow is 'top-to-bottom' we can't simply ask the #copyright div to stick to the bottom of his parent without absolutely positioning of some sort, But if we wanted the #copyright div to stick to the top of his parent, it will be very simple - because this is the normal flow way.
So we will use this in our advantage.
we will change the order of the divs in the HTML, now the #copyright div is at the top, and the content follow it right away.
we also make the content div stretch all the way (using pseudo elements and clearing techniques)
now it's just a matter of inverting that order back in the view. that can be easily done with CSS transform.
We rotate the container by 180deg, and now: up-is-down. (and we inverse back the content to look normal again)
If we want to have a scroolbar within the content area, we need to apply a little bit more of CSS magic. as can be showed Here [in that example, the content is below a header - but its the same idea]
* {
margin: 0;
padding: 0;
}
html,
body,
#Container {
height: 100%;
color: white;
}
#Container:before {
content: '';
height: 100%;
float: left;
}
#Copyright {
background-color: green;
}
#Stretch {
background-color: blue;
}
#Stretch:after {
content: '';
display: block;
clear: both;
}
#Container,
#Container>div {
-moz-transform: rotateX(180deg);
-ms-transform: rotateX(180deg);
-o-transform: rotate(180deg);
-webkit-transform: rotateX(180deg);
transform: rotateX(180deg);
}
<div id="Container">
<div id="Copyright">
Copyright Foo web designs
</div>
<div id="Stretch">
<!-- Other elements here -->
<div>Element 1</div>
<div>Element 2</div>
</div>
</div>
CSS Grid
Since the usage of CSS Grid is increasing, I would like to suggest align-self to the element that is inside a grid container.
align-self can contain any of the values: end, self-end, flex-end for the following example.
#parent {
display: grid;
}
#child1 {
align-self: end;
}
/* Extra Styling for Snippet */
#parent {
height: 150px;
background: #5548B0;
color: #fff;
padding: 10px;
font-family: sans-serif;
}
#child1 {
height: 50px;
width: 50px;
background: #6A67CE;
text-align: center;
vertical-align: middle;
line-height: 50px;
}
<div id="parent">
<!-- Other elements here -->
<div id="child1">
1
</div>
</div>
Create another container div for the elements above #copyright. Just above copyright add a new div:
<div style="clear:both;"></div>
It will force the footer to be under everything else, just like in the case of using relative positioning (bottom:0px;).
Try this;
<div id="container">
<div style="height: 100%; border:1px solid #ff0000;">
<!-- Other elements here -->
</div>
</div>
<div id="copyright" style="position:relative;border:1px solid #00ff00;top:-25px">
Copyright Foo web designs
</div>
While none of the answers provided here seemed to apply or work in my particular case, I came across this article which provides this neat solution :
#container {
display: table;
}
#copyright {
display: table-footer-group;
}
I find it very useful for applying responsive design for mobile display without having to reorder all the html code of a website, setting body itself as a table.
Note that only the first table-footer-group or table-header-group will be rendered as such : if there are more than one, the others will be rendered as table-row-group.
You can indeed align the box to the bottom without using position:absolute if you know the height of the #container using the text alignment feature of inline-block elements.
Here you can see it in action.
This is the code:
#container {
/* So the #container most have a fixed height */
height: 300px;
line-height: 300px;
background:Red;
}
#container > * {
/* Restore Line height to Normal */
line-height: 1.2em;
}
#copyright {
display:inline-block;
vertical-align:bottom;
width:100%; /* Let it be a block */
background:green;
}
Using the translateY and top property
Just set element child to position: relative and than move it top: 100% (that's the 100% height of the parent) and stick to bottom of parent by transform: translateY(-100%) (that's -100% of the height of the child).
BenefitS
you do not take the element from the page flow
it is dynamic
But still just workaround :(
.copyright{
position: relative;
top: 100%;
transform: translateY(-100%);
}
Don't forget prefixes for the older browser.
CodePen link here.
html, body {
width: 100%;
height: 100%;
}
.overlay {
min-height: 100%;
position: relative;
}
.container {
width: 900px;
position: relative;
padding-bottom: 50px;
}
.height {
width: 900px;
height: 50px;
}
.footer {
width: 900px;
height: 50px;
position: absolute;
bottom: 0;
}
<div class="overlay">
<div class="container">
<div class="height">
content
</div>
</div>
<div class="footer">
footer
</div>
</div>
If you want it to "stick" to the bottom, regardless of the height of container, then absolute positioning is the way to go. Of course, if the copyright element is the last in the container it'll always be at the bottom anyway.
Can you expand on your question? Explain exactly what you're trying to do (and why you don't want to use absolute positioning)?
If you do not know the height of child block:
#parent {
background:green;
width:200px;
height:200px;
display:table-cell;
vertical-align:bottom;
}
.child {
background:red;
vertical-align:bottom;
}
<div id="parent">
<div class="child">child
</div>
</div>
http://jsbin.com/ULUXIFon/3/edit
If you know the height of the child block add the child block then add padding-top/margin-top:
#parent {
background:green;
width:200px;
height:130px;
padding-top:70px;
}
.child {
background:red;
vertical-align:
bottom;
height:130px;
}
<div id="parent">
<div class="child">child
</div>
</div>
You can use grid by assigning the available space to the content at the top:
#container {
display: grid;
grid-template-rows: 1fr auto;
height: 10rem; /* or 100% or anything */
}
<div id="container">
This is random content.
<div id="copyright">
Copyright Foo web designs
</div>
</div>
Also, if there's stipulations with using position:absolute; or position:relative;, you can always try padding parent div or putting a margin-top:x;. Not a very good method in most cases, but it may come in handy in some cases.
Solution for this specific scenario:
Place inner at the bottom of parent . The height of the parent is set by the height of its "tallest" sibling
The set up:
I have a row with multiple <div class="container">
These <div class="container"> are next to each other inside another <div class="supercontainer">
Each <div class="container"> has 3 inner divs on top of each other: <div class="title">, <div class="content">, <div class="footer">
The desired result:
All <div class="container"> have the same height. The height is not defined in px, it will be the height of the "tallest" among them.
<div class="title"> should be at the top of <div class="container">
<div class="content"> should be placed below <div class="title">
<div class="footer"> should be placed at the bottom of <div class="container"> without overlapping with the previous content
This is the current state: https://codepen.io/xavier-atero/pen/ExvWQww
.supercontainer {
border: solid 1px black;
display: flex;
}
.container, .other-container {
position: relative;
border: solid 1px red;
width: 200px;
margin: 10px;
}
.title {
margin: 10px;
border: solid 1px blue;
}
.content {
margin: 10px;
border: solid 1px cyan;
}
.footer {
margin: 10px;
background: lime;
}
<body>
<div class="supercontainer">
<div class="container">
<div class="title">
This part represents the title and it is placed on top
</div>
<div class="content">
This one represents the body and it is placed below the title
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
<div class="other-container">
<div class="title">
This part represents the title and it is placed on top.
</div>
<div class="content">
This one represents the body and it is placed below the title. This one is longer than the first one to stretch the parent div. Since it is longer, the footers of the two containers are not alinged.
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
</div>
</body>
__________ Solution with FLEXBOX __________
This is the outcome: https://codepen.io/xavier-atero/pen/MWvpBMz
.supercontainer {
border: solid 1px black;
display: flex;
}
.container, .other-container {
position: relative;
border: solid 1px red;
width: 200px;
margin: 10px;
display: flex;
flex-direction: column;
}
.title {
margin: 10px;
border: solid 1px blue;
}
.content {
margin: 10px;
border: solid 1px cyan;
}
.footer {
margin: 10px;
background: lime;
margin-top: auto;
border: solid 1px fuchsia;
}
<body>
<div class="supercontainer">
<div class="container">
<div class="title">
This part represents the title and it is placed on top
</div>
<div class="content">
This one represents the body and it is placed below the title
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
<div class="other-container">
<div class="title">
This part represents the title and it is placed on top.
</div>
<div class="content">
This one represents the body and it is placed below the title. This one is longer than the first one to stretch the parent div. Since it is longer, the footers of the two containers are not alinged.
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
</div>
</body>
__________ Solution with TABLE-ROW __________
This is the outcome: https://codepen.io/xavier-atero/pen/rNzyKJm
.supercontainer {
border: solid 1px black;
display: flex;
}
.container, .other-container {
position: relative;
border: solid 1px red;
width: 200px;
margin: 10px;
border-collapse:collapse;
display : table;
}
.title {
margin: 10px;
border: solid 1px blue;
}
.content {
margin: 10px;
border: solid 1px cyan;
}
.footer {
margin: 10px;
background: lime;
border: solid 1px fuchsia;
display: table-row;
vertical-align: bottom;
height: 1px;
}
<body>
<div class="supercontainer">
<div class="container">
<div class="title">
This part represents the title and it is placed on top
</div>
<div class="content">
This one represents the body and it is placed below the title
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
<div class="other-container">
<div class="title">
This part represents the title and it is placed on top.
</div>
<div class="content">
This one represents the body and it is placed below the title. This one is longer than the first one to stretch the parent div. Since it is longer, the footers of the two containers are not alinged.
</div>
<div class="footer">
And this one is the footer. It should always be at the bottom of the container
</div>
</div>
</div>
</body>
#container{width:100%; float:left; position:relative;}
#copyright{position:absolute; bottom:0px; left:0px; background:#F00; width:100%;}
#container{background:gray; height:100px;}
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
</div>
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
</div>
Don't wanna use "position:absolute" for sticky footer at bottom. Then you can do this way:
html,
body {
height: 100%;
margin: 0;
}
.wrapper {
min-height: 100%;
/* Equal to height of footer */
/* But also accounting for potential margin-bottom of last child */
margin-bottom: -50px;
}
.footer{
background: #000;
text-align: center;
color: #fff;
}
.footer,
.push {
height: 50px;
}
<html>
<body>
<!--HTML Code-->
<div class="wrapper">
<div class="content">content</div>
<div class="push"></div>
</div>
<footer class="footer">test</footer>
</body>
</html>
Here is an approach targeted at making an element with a known height and width (at least approximately) float to the right and stay at the bottom, while behaving as an inline element to the other elements. It is focused at the bottom-right because you can place it easily in any other corner through other methods.
I needed to make a navigation bar which would have the actual links at the bottom right, and random sibling elements, while ensuring that the bar itself stretched properly, without disrupting the layout. I used a "shadow" element to occupy the navigation bar's links' space and added it at the end of the container's child nodes.
<!DOCTYPE html>
<div id="container">
<!-- Other elements here -->
<div id="copyright">
Copyright Foo web designs
</div>
<span id="copyright-s">filler</span>
</div>
<style>
#copyright {
display:inline-block;
position:absolute;
bottom:0;
right:0;
}
#copyright-s {
float:right;
visibility:hidden;
width:20em; /* ~ #copyright.style.width */
height:3em; /* ~ #copyright.style.height */
}
</style>
Maybe this helps someone: You can always place the div outside the other div and then push it upwards using negative margin:
<div id="container" style="background-color: #ccc; padding-bottom: 30px;">
Hello!
</div>
<div id="copyright" style="margin-top: -20px;">
Copyright Foo web designs
</div>
Just because this hasn't been mentioned at all, what usually works well in situations like yours:
Placing the copyright-div after the container-div
You would only have to format the copyright-div in a similar way to the other container (same overall width, centering, etc.), and all is fine.
CSS:
#container, #copyright {
width: 1000px;
margin:0 auto;
}
HTML:
<div id="container">
<!-- Other elements here -->
</div>
<div id="copyright">
Copyright Foo web designs
</div>
The only time this might not be ideal is when your container-div is declared with height:100%, and the user would need to scroll down to see the copyright. But even still you could work around (e.g. margin-top:-20px - when the height of your copyright element is 20px).
No absolute positioning
No table layout
No crazy css, that looks different in every other browser (well IE at least, you know)
Simple and clear formatting
Aside: I know the OP asked for a solution that "... sticks to the bottom of the 'container' div ...", and not something under it, but come on, people are looking for good solutions here, and this is one!
There is nothing called float:bottom in CSS. The best way is using positioning in such cases:
position:absolute;
bottom:0;
For those only have one child in the container, you can use the table-cell and vertical-align approach which worked reliably for positioning a single div at the bottom of its parent.
Note that using table-footer-group as other answers mentioned will break the height calculation of parent table.
#container {
display: table;
width: 100%;
height: 200px;
}
#item {
display: table-cell;
vertical-align: bottom;
}
<div id="container">
<div id="item">Single bottom item</div>
</div>
According: w3schools.com
An element with position: absolute; is positioned relative to the
nearest positioned ancestor (instead of positioned relative to the
viewport, like fixed).
So you need to position the parent element with something either relative or absolute, etc and position the desired element to absolute and latter set bottom to 0.

Have content fill remaining screen-space [duplicate]

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.
2015 update: the flexbox approach
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
Working example
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.
There really isn't a sound, cross-browser way to do this in CSS. Assuming your layout has complexities, you need to use JavaScript to set the element's height. The essence of what you need to do is:
Element Height = Viewport height - element.offset.top - desired bottom margin
Once you can get this value and set the element's height, you need to attach event handlers to both the window onload and onresize so that you can fire your resize function.
Also, assuming your content could be larger than the viewport, you will need to set overflow-y to scroll.
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>
Instead of using tables in the markup, you could use CSS tables.
Markup
<body>
<div>hello </div>
<div>there</div>
</body>
(Relevant) CSS
body
{
display:table;
width:100%;
}
div
{
display:table-row;
}
div+ div
{
height:100%;
}
FIDDLE1 and FIDDLE2
Some advantages of this method are:
1) Less markup
2) Markup is more semantic than tables, because this is not tabular data.
3) Browser support is very good: IE8+, All modern browsers and mobile devices (caniuse)
Just for completeness, here are the equivalent Html elements to css properties for the The CSS table model
table { display: table }
tr { display: table-row }
thead { display: table-header-group }
tbody { display: table-row-group }
tfoot { display: table-footer-group }
col { display: table-column }
colgroup { display: table-column-group }
td, th { display: table-cell }
caption { display: table-caption }
CSS only Approach (If height is known/fixed)
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...
Demo
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.
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>
Codepen sample
An alternate solution, with a div centered within the content div
Used:
height: calc(100vh - 110px);
code:
.header { height: 60px; top: 0; background-color: green}
.body {
height: calc(100vh - 110px); /*50+60*/
background-color: gray;
}
.footer { height: 50px; bottom: 0; }
<div class="header">
<h2>My header</h2>
</div>
<div class="body">
<p>The body</p>
</div>
<div class="footer">
My footer
</div>
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:
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
JSFiddle live preview
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.
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
Disclaimer: The accepted answer gives the idea of the solution, but I'm finding it a bit bloated with an unnecessary wrapper and css rules. Below is a solution with very few css rules.
HTML 5
<body>
<header>Header with an arbitrary height</header>
<main>
This container will grow so as to take the remaining height
</main>
</body>
CSS
body {
display: flex;
flex-direction: column;
min-height: 100vh; /* body takes whole viewport's height */
}
main {
flex: 1; /* this will make the container take the free space */
}
Solution above uses viewport units and flexbox, and is therefore IE10+, providing you use the old syntax for IE10.
Codepen to play with: link to codepen
Or this one, for those needing the main container to be scrollable in case of overflowing content: link to codepen
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!
What worked for me (with a div within another div and I assume in all other circumstances) is to set the bottom padding to 100%. That is, add this to your css / stylesheet:
padding-bottom: 100%;
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>
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>
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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<style type="text/css">
body
,html
{
height: 100%;
margin: 0;
padding: 0;
color: #FFF;
}
#header
{
float: left;
width: 100%;
background: red;
}
#content
{
height: 100%;
overflow: auto;
background: blue;
}
</style>
</head>
<body>
<div id="content">
<div id="header">
Header
<p>Header stuff</p>
</div>
Content
<p>Content stuff</p>
</div>
</body>
</html>
In all sane browsers, you can put the "header" div before the content, as a sibling, and the same CSS will work. However, IE7- does not interpret the height correctly if the float is 100% in that case, so the header needs to be IN the content, as above. The overflow: auto will cause double scroll bars on IE (which always has the viewport scrollbar visible, but disabled), but without it, the content will clip if it overflows.
CSS Grid Solution
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
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>
I wresteled with this for a while and ended up with the following:
Since it is easy to make the content DIV the same height as the parent but apparently difficult to make it the parent height minus the header height I decided to make content div full height but position it absolutely in the top left corner and then define a padding for the top which has the height of the header. This way the content displays neatly under the header and fills the whole remaining space:
body {
padding: 0;
margin: 0;
height: 100%;
overflow: hidden;
}
#header {
position: absolute;
top: 0;
left: 0;
height: 50px;
}
#content {
position: absolute;
top: 0;
left: 0;
padding-top: 50px;
height: 100%;
}
Why not just like this?
html, body {
height: 100%;
}
#containerInput {
background-image: url('../img/edit_bg.jpg');
height: 40%;
}
#containerControl {
background-image: url('../img/control_bg.jpg');
height: 60%;
}
Giving you html and body (in that order) a height and then just give your elements a height?
Works for me
You can actually use display: table to split the area into two elements (header and content), where the header can vary in height and the content fills the remaining space. This works with the whole page, as well as when the area is simply the content of another element positioned with position set to relative, absolute or fixed. It will work as long as the parent element has a non-zero height.
See this fiddle and also the code below:
CSS:
body, html {
height: 100%;
margin: 0;
padding: 0;
}
p {
margin: 0;
padding: 0;
}
.additional-padding {
height: 50px;
background-color: #DE9;
}
.as-table {
display: table;
height: 100%;
width: 100%;
}
.as-table-row {
display: table-row;
height: 100%;
}
#content {
width: 100%;
height: 100%;
background-color: #33DD44;
}
HTML:
<div class="as-table">
<div id="header">
<p>This header can vary in height, it also doesn't have to be displayed as table-row. It will simply take the necessary space and the rest below will be taken by the second div which is displayed as table-row. Now adding some copy to artificially expand the header.</p>
<div class="additional-padding"></div>
</div>
<div class="as-table-row">
<div id="content">
<p>This is the actual content that takes the rest of the available space.</p>
</div>
</div>
</div>
style="height:100vh"
solved the problem for me. In my case I applied this to the required div
Vincent, I'll answer again using your new requirements. Since you don't care about the content being hidden if it's too long, you don't need to float the header. Just put overflow hidden on the html and body tags, and set #content height to 100%. The content will always be longer than the viewport by the height of the header, but it'll be hidden and won't cause scrollbars.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<style type="text/css">
body, html {
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
color: #FFF;
}
p {
margin: 0;
}
#header {
background: red;
}
#content {
position: relative;
height: 100%;
background: blue;
}
#content #positioned {
position: absolute;
top: 0;
right: 0;
}
</style>
</head>
<body>
<div id="header">
Header
<p>Header stuff</p>
</div>
<div id="content">
Content
<p>Content stuff</p>
<div id="positioned">Positioned Content</div>
</div>
</body>
</html>
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/
Try this
var sizeFooter = function(){
$(".webfooter")
.css("padding-bottom", "0px")
.css("padding-bottom", $(window).height() - $("body").height())
}
$(window).resize(sizeFooter);
I had the same problem but I could not make work the solution with flexboxes above. So I created my own template, that includes:
a header with a fixed size element
a footer
a side bar with a scrollbar that occupies the remaining height
content
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>
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...
I found a quite simple solution, because for me it was just a design issue.
I wanted the rest of the Page not to be white below the red footer.
So i set the pages background color to red. And the contents backgroundcolor to white.
With the contents height set to eg. 20em or 50% an almost empty page won't leave the whole page red.

How to layout HTML elements relative to bottom?

I am trying to layout 3 elements in react (without jQuery and bootstrap). See the image:
Essentially, the application has a container div that takes 100% height of Body, which is set to window height. It has three child elements:
Header: Positioned relative to the top of container
Footer: Positioned relative to the bottom of container; may have variable height
Contents: Positioned relative to the top of footer
Getting container and header in place is easy but footer and contents are the difficult pieces. My code looks something like this:
CSS:
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.container {
height: 100%;
}
#footer: {
position: fixed,
right: 0,
bottom: 0,
left: 0,
}
I am trying to understand best way to achieve it. Can you please suggest how should I write CSS?
The HTML:
<body>
<div class="container">
<header>
</header>
<div class="content">
</div>
<footer>
</footer>
</div>
</body>
The CSS:
body {
margin: 0;
padding: 0;
background-color: white;
}
.container {
width: 100vw;
height: 100vh;
background-color: black;
display: flex;
flex-direction: column;
}
header {
flex: 0 0 120px;
background-color: green;
}
.content {
flex: 1 1;
background-color: blue;
overflow: hidden;
}
footer {
flex: 0 0 10%;
background-color: red;
}
Codepen: https://codepen.io/anon/pen/WZKwEb
Explanation: The layout uses CSS3 flexbox. All elements have a different background color to give visual feedback of proportions and heights.
The top level container div is the flexbox container. Its height and width are set to 100vh (100% viewport height) and 100vw (100% viewport width) respectively.
The header and footer are set to specific heights (the header in pixels, the footer in %, for the sake of demonstrating both), while the content div is set to occupy the remaining space, and grow or shrink accordingly (flex: 1 1).
If the contents of the header or footer overflows their specific heights, their height will be adjusted accordingly, at the expense of the content div. The content div has its overflow set to hidden, meaning its content will neither overflow into the header or footer, nor cause a scrollbar to appear, instead the overflowing content will just be hidden.
Please check the updated answer. Hope it is helpful to you. Kindly review the answer. Here i first calculated the height of header and footer and window height and provided remaining height to content by subtracting height of header and footer from it. Jindy review the jquery code. Hope that is helpful to you.
var WindowsSize=function(){
var h=$(window).height(),
w=$(window).width();
headerHeight = $('.header').height();
footerHeight = $('.footer').height();
h=h-headerHeight-footerHeight;
$(".content").height(h);
};
$(document).ready(function(){WindowsSize();});
$(window).resize(function(){WindowsSize();});
body {
margin:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="header">
test
</div>
<div class="content">
test
</div>
<div class="footer">
test
</div>
</div>
This is how you can do with plain css vey less code
https://codepen.io/bhupinderkumarbl/pen/LzBGZN
.content {
height: 400px;
border: 1px solid;
display: flex;
flex-direction: column;
justify-content:space-between
}
h1, h2 {
margin: 0;
}
<div class="content">
<h1>heading 1</h1>
<p>Some text more or less</p>
Click me
</div>
Super clean and simple code below which is fully flexible also.
body {
margin:0;
}
.container{
min-height:100vh;
display:flex;
flex-direction:column;
}
section, header, footer{
background:#EEE;
padding:20px;
border:5px solid #FFF;
text-align:center;
}
section{
flex:1;
}
<div class="container">
<header>Header</header>
<section>Content</section>
<footer>Footer</footer>
</div>

Make a div fill the height of the remaining screen space

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.
2015 update: the flexbox approach
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
Working example
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.
There really isn't a sound, cross-browser way to do this in CSS. Assuming your layout has complexities, you need to use JavaScript to set the element's height. The essence of what you need to do is:
Element Height = Viewport height - element.offset.top - desired bottom margin
Once you can get this value and set the element's height, you need to attach event handlers to both the window onload and onresize so that you can fire your resize function.
Also, assuming your content could be larger than the viewport, you will need to set overflow-y to scroll.
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>
Instead of using tables in the markup, you could use CSS tables.
Markup
<body>
<div>hello </div>
<div>there</div>
</body>
(Relevant) CSS
body
{
display:table;
width:100%;
}
div
{
display:table-row;
}
div+ div
{
height:100%;
}
FIDDLE1 and FIDDLE2
Some advantages of this method are:
1) Less markup
2) Markup is more semantic than tables, because this is not tabular data.
3) Browser support is very good: IE8+, All modern browsers and mobile devices (caniuse)
Just for completeness, here are the equivalent Html elements to css properties for the The CSS table model
table { display: table }
tr { display: table-row }
thead { display: table-header-group }
tbody { display: table-row-group }
tfoot { display: table-footer-group }
col { display: table-column }
colgroup { display: table-column-group }
td, th { display: table-cell }
caption { display: table-caption }
CSS only Approach (If height is known/fixed)
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...
Demo
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.
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>
Codepen sample
An alternate solution, with a div centered within the content div
Used:
height: calc(100vh - 110px);
code:
.header { height: 60px; top: 0; background-color: green}
.body {
height: calc(100vh - 110px); /*50+60*/
background-color: gray;
}
.footer { height: 50px; bottom: 0; }
<div class="header">
<h2>My header</h2>
</div>
<div class="body">
<p>The body</p>
</div>
<div class="footer">
My footer
</div>
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:
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
JSFiddle live preview
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.
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
Disclaimer: The accepted answer gives the idea of the solution, but I'm finding it a bit bloated with an unnecessary wrapper and css rules. Below is a solution with very few css rules.
HTML 5
<body>
<header>Header with an arbitrary height</header>
<main>
This container will grow so as to take the remaining height
</main>
</body>
CSS
body {
display: flex;
flex-direction: column;
min-height: 100vh; /* body takes whole viewport's height */
}
main {
flex: 1; /* this will make the container take the free space */
}
Solution above uses viewport units and flexbox, and is therefore IE10+, providing you use the old syntax for IE10.
Codepen to play with: link to codepen
Or this one, for those needing the main container to be scrollable in case of overflowing content: link to codepen
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!
What worked for me (with a div within another div and I assume in all other circumstances) is to set the bottom padding to 100%. That is, add this to your css / stylesheet:
padding-bottom: 100%;
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>
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>
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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<style type="text/css">
body
,html
{
height: 100%;
margin: 0;
padding: 0;
color: #FFF;
}
#header
{
float: left;
width: 100%;
background: red;
}
#content
{
height: 100%;
overflow: auto;
background: blue;
}
</style>
</head>
<body>
<div id="content">
<div id="header">
Header
<p>Header stuff</p>
</div>
Content
<p>Content stuff</p>
</div>
</body>
</html>
In all sane browsers, you can put the "header" div before the content, as a sibling, and the same CSS will work. However, IE7- does not interpret the height correctly if the float is 100% in that case, so the header needs to be IN the content, as above. The overflow: auto will cause double scroll bars on IE (which always has the viewport scrollbar visible, but disabled), but without it, the content will clip if it overflows.
CSS Grid Solution
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
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>
I wresteled with this for a while and ended up with the following:
Since it is easy to make the content DIV the same height as the parent but apparently difficult to make it the parent height minus the header height I decided to make content div full height but position it absolutely in the top left corner and then define a padding for the top which has the height of the header. This way the content displays neatly under the header and fills the whole remaining space:
body {
padding: 0;
margin: 0;
height: 100%;
overflow: hidden;
}
#header {
position: absolute;
top: 0;
left: 0;
height: 50px;
}
#content {
position: absolute;
top: 0;
left: 0;
padding-top: 50px;
height: 100%;
}
Why not just like this?
html, body {
height: 100%;
}
#containerInput {
background-image: url('../img/edit_bg.jpg');
height: 40%;
}
#containerControl {
background-image: url('../img/control_bg.jpg');
height: 60%;
}
Giving you html and body (in that order) a height and then just give your elements a height?
Works for me
You can actually use display: table to split the area into two elements (header and content), where the header can vary in height and the content fills the remaining space. This works with the whole page, as well as when the area is simply the content of another element positioned with position set to relative, absolute or fixed. It will work as long as the parent element has a non-zero height.
See this fiddle and also the code below:
CSS:
body, html {
height: 100%;
margin: 0;
padding: 0;
}
p {
margin: 0;
padding: 0;
}
.additional-padding {
height: 50px;
background-color: #DE9;
}
.as-table {
display: table;
height: 100%;
width: 100%;
}
.as-table-row {
display: table-row;
height: 100%;
}
#content {
width: 100%;
height: 100%;
background-color: #33DD44;
}
HTML:
<div class="as-table">
<div id="header">
<p>This header can vary in height, it also doesn't have to be displayed as table-row. It will simply take the necessary space and the rest below will be taken by the second div which is displayed as table-row. Now adding some copy to artificially expand the header.</p>
<div class="additional-padding"></div>
</div>
<div class="as-table-row">
<div id="content">
<p>This is the actual content that takes the rest of the available space.</p>
</div>
</div>
</div>
style="height:100vh"
solved the problem for me. In my case I applied this to the required div
Vincent, I'll answer again using your new requirements. Since you don't care about the content being hidden if it's too long, you don't need to float the header. Just put overflow hidden on the html and body tags, and set #content height to 100%. The content will always be longer than the viewport by the height of the header, but it'll be hidden and won't cause scrollbars.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<style type="text/css">
body, html {
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
color: #FFF;
}
p {
margin: 0;
}
#header {
background: red;
}
#content {
position: relative;
height: 100%;
background: blue;
}
#content #positioned {
position: absolute;
top: 0;
right: 0;
}
</style>
</head>
<body>
<div id="header">
Header
<p>Header stuff</p>
</div>
<div id="content">
Content
<p>Content stuff</p>
<div id="positioned">Positioned Content</div>
</div>
</body>
</html>
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/
Try this
var sizeFooter = function(){
$(".webfooter")
.css("padding-bottom", "0px")
.css("padding-bottom", $(window).height() - $("body").height())
}
$(window).resize(sizeFooter);
I had the same problem but I could not make work the solution with flexboxes above. So I created my own template, that includes:
a header with a fixed size element
a footer
a side bar with a scrollbar that occupies the remaining height
content
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>
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...
I found a quite simple solution, because for me it was just a design issue.
I wanted the rest of the Page not to be white below the red footer.
So i set the pages background color to red. And the contents backgroundcolor to white.
With the contents height set to eg. 20em or 50% an almost empty page won't leave the whole page red.