56

Is it possible to make the wrapper fill the window height (no scrolling) and the center div scrollable without messing around with pixels and javascript?

<div id="wrapper">
  <h1>Header</h1>
  <div id="center">
    <div style="height:1000px">high content</div>
  </div>
  <div id="footer">Footer</div>
</div>

Basically I want the header to be visible at the top and the footer to be always visible at the bottom and have a scrollable content in the center which occupies the remaning height.
The header, footer and center divs' heights are all unknown (no set px or %, i.e. variable font-size or padding). Is it possible with pure CSS?

Dan Dascalescu
  • 110,650
  • 40
  • 276
  • 363
danial
  • 3,853
  • 2
  • 28
  • 38
  • Are you trying to accomplish the same essential thing as in this question? Though variable heights would make it trickier. http://stackoverflow.com/questions/8555157/full-screen-css-with-minimum-size/8555283#8555283 – justisb Dec 19 '11 at 01:05
  • Similar but the layout without a fixed height header or footer, so changing the content of header or footer or adding elemets to them, won't affect the css properties of the center div. – danial Dec 19 '11 at 03:19

4 Answers4

82

2014 UPDATE: The modern way to solve this layout problem is to use the flexbox CSS model. It's supported by all major browsers and IE11+.


2012: The correct way to do this with CSS alone is to use display: table and display: table-row. These are supported by all major browsers, starting with IE8. This is not using tables for display. You'll use divs:

html, body {
    height: 100%;
    margin: 0;
}
.wrapper {
    display: table;
    height: 100%;
    width: 100%;
    background: yellow;  /* just to make sure nothing bleeds */
}
.header {
    display: table-row;
    background: gray;
}
.content {
    display: table-row;  /* height is dynamic, and will expand... */
    height: 100%;        /* ...as content is added (won't scroll) */
    background: turquoise;
}
.footer {
    display: table-row;
    background: lightgray;
}
<div class="wrapper">
    <div class="header">
        <h1>Header</h1>
        <p>Header of variable height</p>
    </div>
    <div class="content">
        <h2>Content that expands in height dynamically to adjust for new content</h2>
        Content height will initially be the remaining
        height in its container (<code>.wrapper</code>).
        <!-- p style="font-size: 4000%">Tall content</p -->
    </div>
    <div class="footer">
        <h3>Sticky footer</h3>
        <p>Footer of variable height</p>
    </div>
</div>

That's it. The divs are wrapped as you'd expect.

Community
  • 1
  • 1
Dan Dascalescu
  • 110,650
  • 40
  • 276
  • 363
  • 4
    I would like to add the following refinement: http://jsfiddle.net/6dbyr/ This allows to have a scrollable area inside the cell that takes up the full height. – user132837 May 13 '13 at 14:30
  • 1
    Argh... and a big breaker, that refinement doesn't work in Firefox. See https://bugzilla.mozilla.org/show_bug.cgi?id=794644 But this does: http://stackoverflow.com/questions/12605816/sticky-flexible-footers-and-headers-css-working-fine-in-webkit-but-not-in-gecko/12622740#12622740 – user132837 May 14 '13 at 09:05
  • Note that content (if its height is bigger than the wrapper height) will overflow in IE (even IE10). – Boris D. Teoharov Oct 17 '13 at 22:47
  • 1
    `display: table-row` will remove all the borders from the items it is applied to – danza Feb 13 '14 at 11:02
  • 3
    After playing around with http://stackoverflow.com/questions/12605816/sticky-flexible-footers-and-headers-css-working-fine-in-webkit-but-not-in-gecko/12622740#12622740 got this working in all browsers except Opera: http://jsfiddle.net/Uc9E2/ – danial Apr 03 '14 at 15:11
  • Any chance to do this if the header element can't be touched (it already is display: table itself...)? – andig Aug 09 '14 at 15:17
  • 1
    @danial this really helped me today, thank you very much. It now works in Opera too, since it's much similar to Chrome these days. I think you should answer yourself with this method, because I've been trying this and that, making up markup myself, googling, trying various solutions and only yours did what I need in every browser and even with zero changes to adapt it. This was very helpful fiddle that should get more attention. – waterplea Nov 16 '14 at 13:06
5

A cross-browser solution derived from Dan Dascalescu answer:

http://jsfiddle.net/Uc9E2

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}
.l-fit-height {
    display: table;
    height: 100%;
}
.l-fit-height-row {
    display: table-row;
    height: 1px;
}
.l-fit-height-row-content {
    /* Firefox requires this */
    display: table-cell;
}
.l-fit-height-row-expanded {
    height: 100%;
    display: table-row;
}
.l-fit-height-row-expanded > .l-fit-height-row-content {
    height: 100%;
    width: 100%;
}
@-moz-document url-prefix() {
    .l-scroll {
        /* Firefox requires this to do the absolute positioning correctly */
        display: inline-block;
    }
}
.l-scroll {
    overflow-y: auto;
    position: relative;
    height: 1000px;
}
.l-scroll-content {
    position: absolute;
    top: 0;
    bottom: 0;
    height: 1000px;
    min-height:100px;
}
<div class="l-fit-height">
    <section class="l-fit-height-row">
        <div class="l-fit-height-row-content">
            <p>Header</p>
        </div>
    </section>
    <section class="l-fit-height-row-expanded">
        <div class="l-fit-height-row-content l-scroll">
            <div class="l-scroll-content">
                <p>Foo</p>
            </div>
        </div>
    </section>
    <section class="l-fit-height-row">
        <div class="l-fit-height-row-content">
            <p>Footer</p>
        </div>
    </section>
</div>
Community
  • 1
  • 1
danial
  • 3,853
  • 2
  • 28
  • 38
-2

Using overflow:auto will let you do this.

demo

Brigand
  • 75,952
  • 19
  • 155
  • 166
  • 2
    In your example you set the height to 80%, but I don't know the height of the center div, I just want it to take the remaining space. Thanks – danial Dec 19 '11 at 00:22
  • @danial, do you know the height of the footer and header? (In percents or pixels) – Brigand Dec 19 '11 at 00:30
  • 1
    no I don't, I just updated the question. It depends on the font-size, padding and/or other elements that might be added dynamically. – danial Dec 19 '11 at 00:37
  • If it's possible, I don't know how to do it. The usual approach here is to give the header, content, and footer each a percentage based size. – Brigand Dec 19 '11 at 00:45
  • It can be done with `display: table` and `display: table-row`. See [my answer](http://stackoverflow.com/a/12242226/1269037). – Dan Dascalescu Sep 03 '12 at 05:04
-2

So what you are talking about is a sticky footer. I went and did some more research and here is what I have for you.

<div id="wrapper" style="height:100%">
<div id="header" style="float:none;"><h1>Header</h1></div>

<div style="overflow:scroll;float:none;height:auto;">high content</div>

<div id="footer" style="clear:both;position:fixed;bottom:0px;"><h1>Footer</h1></div>
</div>

This will give you a sticky footer. The key is position:fixed and bottom:0px; Unfortunately this means it also hovers above any content in the scrollview. So far there seems to be only Javascript to figure this out but I will keep looking.

Kevrone
  • 530
  • 1
  • 7
  • 21
  • 2
    And it seems from my research that the only way to do what you are asking is via javascript as css doesn't support referenced heights 'i.e height = (page.height - (header.height + footer.height) – Kevrone Dec 19 '11 at 01:50