8

I have this html structure:

<body>
    <div id="container">
        <div id="header">Not empty</div>
        <div id="content">
            <div id="inner_header">Not empty</div>
            <div id="scrollable_content">Very long content</div>
        </div>
    </div>
</body>

I want the page to have a fixed height equal to the height of the screen, and I also want a vertical scrollbar for the div scrollable_content.

I have tried with these styles, but the page I get is larger than the screen, so I get two scrollbars:

html, body {
    height:100%;
}
div#container {
    height:100%;
}
div#scrollable_content {
    height:100%;
    overflow-y:auto;
    position:absolute;
}

How can I do this with CSS3?

Edit: I found a solution using jQuery (see below). I'd like to know if this is possible using only CSS3?

Thanks in advance!

alf
  • 18,372
  • 10
  • 61
  • 92
  • does the #header e #inner_header hava a fixed height? It can be done solely with CSS if they do – Vitor M Sep 19 '11 at 22:11

4 Answers4

12

When you absolutely position an element it comes out of the flow of the page. Please take a look at this fiddle. Note the green box causes two vertical scrollbars to appear.

http://jsfiddle.net/gX2DG/

To get a single scrollbar that only appears below the header, you will need to modify your CSS. This CSS works with fixed height headers only.

  1. Zero out margin/padding on html/body and set overflow:hidden so that they do not trigger the main browser scrollbar
  2. Set body to 100% height so that we can set 100% on divs inside of it
  3. Absolutely position the child div that will contain the scrollable content. Then use left, right, top, bottom to stretch it to fill the screen.

http://jsfiddle.net/J4Ps4/

/* set body to 100% so we can set 100% on internal divs */
/* zero margin/padding and set overflow to hidden to prevent default browser scrollbar */
html, body { height:100%; margin: 0; padding: 0; overflow: hidden; }
div { margin: 0; padding: 0;  }

/* on child div give it absolute positioning and then use top/bottom to stretch it */
/* top must be equal to the height of the header */
div#scrollable_content {
  position: absolute;
  top: 50px;
  bottom: 0px;
  width: 100%;
  overflow-y:auto;
  border: 1px solid green;
}
mrtsherman
  • 39,342
  • 23
  • 87
  • 111
  • Updated my answer with some more tips. Pretty close. I know somebody out there can solve this. – mrtsherman Sep 19 '11 at 22:02
  • This SO question may help you too - http://stackoverflow.com/questions/90178/make-a-div-fill-the-remaining-screen-space – mrtsherman Sep 19 '11 at 22:06
  • Thanks! I can see the problem with the absolute position now. I'm still looking for a perfect solution though, but this one is good :) – alf Sep 20 '11 at 00:03
  • Third times the charm then? I should have asked if header was fixed height. See this fiddle - http://jsfiddle.net/7TqsE/22/ – mrtsherman Sep 20 '11 at 01:26
  • Unbelievable close :) The page is now 50px longer. If you scroll to the bottom of the page you can see the problem. In my scenario the headers are bigger, so the issue is more noticeable. – alf Sep 20 '11 at 01:57
  • hmm, i don't see it longer? In Chrome 13 I see that the very last thing on page reads `Very long content z` – mrtsherman Sep 20 '11 at 03:16
  • Aw crap - I had made one change after posting and link was taking me locally saved version. Remove the height: 100% from the scrollable content div! Then you are all set! http://jsfiddle.net/Qfp5z/2/ – mrtsherman Sep 20 '11 at 04:04
1

My suggestion:

-Have some javascript running to re-size the container div / scrollable_content div to always be 100% height of the browser. If people resize, maximize etc. the browser window your heights will be off.

Depending on the website / application you could have this on a timer (setTimeout) or listening to the resize events of the browser

Check out: jQuery - dynamic div height

or

http://css-discuss.incutio.com/wiki/Hundred_Percent_Height

Update:

Here's what I was talking about: http://jsfiddle.net/7TqsE/21/

I just have it as a resize button, but you can see if you resize the bottom-right window, and click the button, it will resize that div for you to be the height of the containing div.

You can also extend this by getting browser height (this example includes width). I didn't write this script, it's the same one spewed throughout the internet, I just copy it:

if( typeof( window.innerWidth ) == 'number' ) { 

//Non-IE 

myWidth = window.innerWidth;
myHeight = window.innerHeight; 

} else if( document.documentElement && 

( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { 

//IE 6+ in 'standards compliant mode' 

myWidth = document.documentElement.clientWidth; 
myHeight = document.documentElement.clientHeight; 

} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { 

//IE 4 compatible 

myWidth = document.body.clientWidth; 
myHeight = document.body.clientHeight; 

} 
Community
  • 1
  • 1
Ryan Ternier
  • 8,714
  • 4
  • 46
  • 69
0

using the code by mrtsherman, I've made your solution :)

I hope this is it.

http://jsfiddle.net/zzlawlzz/Guq9K/2/

buhbang
  • 715
  • 1
  • 7
  • 18
  • kill the borders and add width to 100% in the `div#scrollable_content` would look better. – buhbang Sep 19 '11 at 22:25
  • 1
    Actually this solution depends on the height of the browser. If I use a screen with a low resolution (a phone for example) it looks very different than using a high resolution screen. – alf Sep 20 '11 at 01:03
0

This is the solution I've found so far using jQuery:

window.setTimeout(function () {
$(document).ready(function () {
    var ResizeTarget = $('#content');
ResizeTarget.resize(function () {
    var target = $('#scrollable_content');
    target.css('height', $(document).height() - $("#header").height() - $("#inner_header").height());
}).trigger('resize');
}); }, 500);
alf
  • 18,372
  • 10
  • 61
  • 92
  • I think your link isn't quite right. Doesn't seem to behave the way you described. Also noticed that your ` – mrtsherman Sep 20 '11 at 01:20
  • Sorry, I was missing the type attribute of the script tag. It's working for me in Chrome and Opera now. – alf Sep 20 '11 at 01:54