Krishna Chaitanya
Krishna Chaitanya

Reputation: 2663

How to set the height of a div to match the remaining height

I have an HTML page which is divided into 4 sections.

  1. Header
  2. Menu
  3. Content
  4. Footer

I am using 1 div for each section and 1 div which wraps all the 4 divs.

My header's height is 50px, the menu's height is 50px, and the footer's height is 20px.

Then I try setting the menu's height to 100%. Menu div is taking the height of its container which is creating scrollbars in my page.

The CSS is as follows:

html, body {
    margin: 0px;
    height: 100%;
    width: 100%;
    min-width: 1024px;
    min-height: 500px;
}

#container {
    width: 100%;
    height: 100%;
}

#header {
    width: 100%;
    height: 50px;
}

#menu {
    width: 100%;
    height: 50px;
}

#content {
    width: 100%;
    height: 100%;
}

#footer {
    width: 100%;
    height: 20px;
}

Is it possible with CSS alone or I have to use JavaScript also?

Upvotes: 2

Views: 3604

Answers (3)

avrahamcool
avrahamcool

Reputation: 14094

Here is another Pure CSS solution, that works without specifying any height whatsoever. [this solution deserves its own answer]

Here's a Working Fiddle

Why is it good?

because maybe your header will change one day affecting his height, or your menu will grow, or your footer will need an extra line causing his height to grow..

all of that changes will cause you to re-fix another height for the changing element, and recalculate the right height for the content.

my solution makes it easier, because all the parts are fluid. let them take the space they need in the page, and the content will always take the remaining height.

Browser support:

Tested On: IE10, Firefox, Chrome, Safari, Opera. (not working on older IE, not tested on other browsers)

any Downsides?

yes. unfortunately, because of the way that this trick works, you will need to change the arrangement of your HTML.

I found a Pure CSS way to create a div container, with two child div's. the first will take the exact height he needs, and the second will take the remaining of the container height's.

but what if I want the opposite scenario, What if I want second div to take his exact space and the first div to take the container's remaining height?

I didn't find an easy way to do that with Pure CSS. thats why, I actually reverse the order of the divs, the first holds the second data, and the second holds the first data, now we let the first div to take his exact height, and the second stretch to the end of the container as we want, and then I rotate their view via CSS to make them appear in order.

For your case it means that you will have to create the HTML in that order.

  1. Header
  2. Menu
  3. Footer
  4. Content

The Solution:

HTML:

<div class="Container">
    <div class="Header">I'm in the header</div>
    <div class="Menu">I'm in the menu</div>
    <div class="HeightTaker">
        <div class="Wrapper Container Inverse">
            <div>
                <div class="Footer">I'm in the footer</div>
            </div>
            <div class="HeightTaker">
                <div class="Wrapper">
                    <div class="Content">
                        I'm in the content
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

CSS:

*
{
    margin: 0;
    padding: 0;
}
html, body, .Container
{
    height: 100%;
}
    .Container:before
    {
        content: '';
        height: 100%;
        float: left;
    }
.HeightTaker
{
    position: relative;
    z-index: 1;
}
    .HeightTaker:after
    {
        content: '';
        clear: both;
        display: block;
    }
.Wrapper
{
    position: absolute;
    width: 100%;
    height: 100%;
}
.Inverse, .Inverse > *
{
    -moz-transform: rotateX(180deg);
    -ms-transform: rotateX(180deg);
    -o-transform: rotate(180deg);
    -webkit-transform: rotateX(180deg);
    transform: rotateX(180deg);
}

.Header
{
    /*for demonstration only*/
    background-color: #bf5b5b;
}
.Menu
{
    /*for demonstration only*/
    background-color: #6ea364;
}
.Content
{
    height: 100%;
    overflow: auto;
    /*for demonstration only*/
    background-color: #90adc1;
}
.Footer
{
    /*for demonstration only*/
    background-color: #b5a8b7;
}

Upvotes: 3

avrahamcool
avrahamcool

Reputation: 14094

Pure CSS Solution

using calc() (CSS3)

Working Fiddle

HTML:

<div id="container">
    <div id="header">header</div>
    <div id="menu">menu</div>
    <div id="content">content</div>
    <div id="footer">footer</div>
</div>

CSS:

html, body {
    margin: 0px;
    height: 100%;
    /*min-width: 1024px;
    min-height: 500px;*/ /*You can uncomment that back if you want)*/
}
#container {
    height: 100%;
}
#header {
    height: 50px;
}
#menu {
    height: 50px;
}
#content {
    height: calc(100% - 120px); /*120 = 50 + 50 + 20*/
    overflow: auto;
}
#footer {
    height: 20px;
}

notice I removed your width:100% because this is the default behavior of a block element like a div.

This can also be done without stating any height at all, with Pure CSS. Check my second answer in that page.

Upvotes: 2

Joseph Marikle
Joseph Marikle

Reputation: 78590

Here's a thought. May not work for your specific problem, but it does address the issue of mixing pixels and percents. Under the current definition of the problem, you use a fixed height for both the top (header, menu) and bottom (footer). But you want to have the content take up the rest. One solution would be to pad the top and bottom of the container with the same height of the header and menu on top and the same height as the footer on the bottom. The problem then is that you have a 100% height container plus 100px on top and 20px on bottom. But there's a CSS convention for that. It's called box-sizing and is very cross browser compatible (as long as you include -moz). in effect, it calculates 100% height after including the padding. Therefore, 100% height plus all the padding still equals 100% height.

In practice it looks like this

HTML

<div class="container">
    <div class="header"></div>
    <div class="menu"></div>
    <div class="content"></div>
    <div class="footer"></div>
</div>

CSS

html, body, .container {
    min-height: 100%;
    background:#eee;
}

.header {
    height: 50px;
    position: relative;
    z-index: 1;
}

.menu {
    height: 50px;
    position: relative;
    z-index: 1;
}

.footer {
    height: 20px;
    width: 100%; /* needed because this one is position absolute */
    bottom: 0%;
    position:absolute;
}

.content {
    height: 100%;
    width: 100%; /* needed because this one is position absolute */
    top: 0%;
    left: 0%;
    padding-top: 100px;
    padding-bottom: 20px;
    position:absolute;
    box-sizing: border-box; /* here's the kicker */
    -moz-box-sizing: border-box;
    overflow: auto; /* don't panic. they take the place of normal scroll bars*/
}

Demo

http://jsfiddle.net/WLR5S

Source

http://jsfiddle.net/WLR5S/show
http://jsfiddle.net/WLR5S/6/show (with -moz for firefox)

Pros

Obviously, the point is that you can have 100% height elements with padding to compensate for footer and header

Cons

You have to use position absolute for the content and footer, and you have to apply position relative with z-index to the header area

EDIT

After a little more experimenting, I found that it's probably best to use height instead of min-height and apply overflow:auto or the like. That way the page has appropriate sidebars if the content gets to be too large: http://jsfiddle.net/WLR5S/2/ or http://jsfiddle.net/WLR5S/3/

Upvotes: 2

Related Questions