Help with a specific 100% height challenge

I’ve read lots on here and elsewhere about the many ways to attack 100% height - and now I’m really confused! My page is arranged like this:

I need the page to have a fixed width - easy enough - I’ve set a width on Outer and have margins set to Auto.

I also need the page to be resizeable vertically:

  • Title - fixed height at the top
  • Footer - fixed height at the bottom
  • Content - varying in height depending on the height of the window/viewport

The rationale for this is to allow Content to expand to use all the available vertical screen space. There will be further elements within Content and I’ll use overflow:auto to make it fit.

This is how I’ve tried to attack it:

  • 100% height on HTML and BODY
  • 100% height on Outer
  • Relative on Outer (just to set a base for positioning)
  • Absolute on footer, sticking it to bottom:0 and left:0

That has got me part of the way, looking at what’s going on with IE’s developer tools, it seems that Outer is sitting at 100% of the viewport.

But, Content doesn’t seem to be contrained by the viewport at all - if I put a border on it, I can never see the bottom. I’ve tried a margin-bottom to bring it clear of the footer, but still with no luck.

So, in short, I guess there are two questions:

  1. how do I get a DIV to size itself to exactly fill the available vertical space
  2. Is there another way to get where I need to go?

I’d welcome any thoughts because I am completely confused by everything I’ve read so far.

Needs to work in IE8 / IE7 / IE6 and FF - that’s all.

Thanks,

Nick

Hi Nick,

Before I suggest anything I must ask you what you expect to happen to content in the middle section when the viewport height is made smaller or when you have content that exceeds the height available?

You have a fixed height of 100% so where is that content to go and how are you to access it?

There won;t be a scrollbar on the main window and the only solution is for scrollbars to appear on your middle section. That immediately creates accessibility problems as everyone expects the scrollbar to be on the main window. Then there is the added problem in that when you narrow the viewport you lose the right scrollbar because the window obscures it so now to navigate the page you have to first horizontally scroll to reveal the vertical scrollbar.

All in all it’s a bad technique all around :slight_smile:

Here is an example that does just that and you can see how awkward it is.

http://www.pmob.co.uk/temp/one-scrollable-div-centred.htm

What would be better is a sticky footer method where the initial height is 100% only but them expands with content or perhaps a [URL=“http://www.pmob.co.uk/search-this/fixed4.htm”]fixed footer that sits on top of the content (except that IE6 needs an expression to make it work).

Hi,
Your best bet would be to set min-height:100% on #outer which will set you up for a Sticky Footer layout.

Then use a repeating BG image on #outer for faux columns.

Something like this

But that link above uses a dummy float to fix the IE8 min-height bug, better to use this method with the pseudo :before and :after elements to fix Opera and IE8.

EDIT:
I must be typing slow today :slight_smile:

Guys, thanks for the advice - quick and comprehensive as usual!

Paul, your example does exactly what my client is looking for. Maybe if I explain a bit more about what’s going on, it wont seem such a bad idea. If it still does, then maybe I need to convince him…

My graphic is probably a bit misleading - the title is only around 60 pixels high and the footer around 20 pixels - the content is bigger than it looks.
The system is for deployment to a closed user group and we can assume a minimum resolution of 1024 x 768.

There will generally be two areas within Content - a set of “search” fields at the top and a set of results at the bottom. The div containing the search fields will have a constant height. The div containing the results should fill the remaining space within Content and should use overflow:auto to provide a scroll bar if it doesn’t all fit. This is the key point: the client wants to make sure that best use is made of available vertical space - if the user has more than 768px available, he can lengthen the screen and see more results without scrolling.

I agree. However in this “business application” the visual cues around what is scrollable are quite logical. We also need to keep the “search” fields visible so the user can see what the results represent.

I think that’s covered by the assumption of 1024x768 minimum.

So, I think I’m off now to extrapolate your example - to add the extra complexity of needing something to scroll within Content, rather than scrolling Content itself…

Thanks again for the pointers! Any other thoughts more than welcome!

I’ve taken Paul’s example and tried to move it to where I need to be. My attempt can be seen here.
It seems that I have two problems:

  • I’ve stuffed something up and caused the footer to move away from the bottom of the viewport.
  • I’m not seeing a scrollbar where I need to, which is on the grey area full of “Bottom part”.

I think the lack of a scroll bar is because I’ve used overflow:hidden on the containing div, but I’m not sure.

So, as a reminder, I’m trying to get the “grey bit” to expand to fill the available vertical space - and it’s doing that; but I need a scroll bar to appear when there’s not enough room for all the content.

Another shove in the right direction would be appreciated.

Thanks,

Nick

Hi,

You’ve messed the content div up with a self closing tag and you need overflow:auto or you won’t get a scrollbar :slight_smile:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Scrollable 100% high element</title>
<style type="text/css">
* {
    margin: 0;
    padding: 0;
}
p {
    margin: 0 0 1em 0;
}
html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}
.wrap {
    width: 800px;
    margin: auto;
    text-align: left;
    height: 100%;
    overflow:hidden;
}
#outer {
    background: #ffffcc;
    position: absolute;
    width: 800px;
    top: 100px;
    bottom: 20px;
    background: green;
    overflow:auto;
}
#top {
    position: absolute;
    width: 800px;
    top: 0px;
    height: 100px;
    background: red;
    overflow: hidden;
}
#bottom {
    position: absolute;
    width: 800px;
    height: 20px;
    bottom: 0;
    background: red;
    overflow: hidden;
}
#menu {
    width: 180px;
    background: yellow;
    float: left;
}
#content {
    background: gray;
    overflow:hidden;
    min-height:0;
}
</style>
<!--[if IE ]>
<style type="text/css">

* html {padding:100px 0 20px} 
* html body{padding:100px 0 20px;padd\\ing:0}
* html #outer{    
    height:100%;
    position:static;
}
* html #content{zoom:1.0}
</style>
<![endif]-->
</head>
<body>
<div class="wrap">
    <div id="top">
        <h1> Header</h1>
    </div>
    <div id="outer">
        <div id="menu">
            <p> Menu</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
        </div>
        <div id="content">
            <div style="height: 200px; background: cyan;">
                <p> Top Part</p>
            </div>
            <div>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
                <p> Bottom Part</p>
            </div>
        </div>
    </div>
    <div id="bottom">
        <p> Bottom</p>
    </div>
</div>
</body>
</html>



If you want the yellow column colour to go all the way down then make it a 180px width repeating image on #outer and repeat it down the y-axis.

Thanks for the continued help Paul.

Still not quite there though! Maybe I’ve not explained well enough.

I’m trying to get just the grey part to scroll - so the yellow, blue (and green) parts all stay put.

That means that, the yellow, blue and grey parts will all have to have their own vertical scrollbars unless you are simply going to hide any overflow in the other sections.

You’ll lose support for IE6 at this point but you can just place all those elements absolutely.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Scrollable 100% high element</title>
<style type="text/css">
* {
    margin: 0;
    padding: 0;
}
p {
    margin: 0 0 1em 0;
}
html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}
.wrap {
    width: 800px;
    margin: auto;
    text-align: left;
    height: 100%;
    overflow:hidden;
}
#outer {
    background: #ffffcc;
    position: absolute;
    width: 800px;
    top: 100px;
    bottom: 20px;
    background: green;
    overflow:hidden;
}
#top {
    position: absolute;
    width: 800px;
    top: 0px;
    height: 100px;
    background: red;
    overflow: hidden;
}
#bottom {
    position: absolute;
    width: 800px;
    height: 20px;
    bottom: 0;
    background: red;
    overflow: hidden;
}
#menu {
    width: 180px;
    background: yellow;
    position:absolute;
    left:0;
    top:0;
    bottom:0;
    z-index:2;
    overflow:auto;
}
#content {
    background: gray;
    overflow:hidden;
    min-height:0;
    position:relative;
    z-index:1;
}
#midtop {
    height: 200px;
    background: cyan;
    overflow:auto;
    margin:0 0 0 180px;
}
#mid {
    position:absolute;
    top:200px;
    bottom:0;
    left:180px;
    right:0;
    overflow:auto;
    background:teal;
}
</style>
<!--[if IE ]>
<style type="text/css">

* html {padding:100px 0 20px} 
* html body{padding:100px 0 20px;padd\\ing:0}
* html #outer{    
    height:100%;
    position:static;
}
* html #content{zoom:1.0}
</style>
<![endif]-->
</head>
<body>
<div class="wrap">
    <div id="top">
        <h1> Header</h1>
    </div>
    <div id="outer">
        <div id="menu">
            <p> Menu</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
        </div>
        <div id="content">
            <div id="midtop">
                <p> Top Part</p>
            </div>
        </div>
        <div id="mid">
            <p> start Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part end</p>
        </div>
    </div>
    <div id="bottom">
        <p> Bottom</p>
    </div>
</div>
</body>
</html>


You may need to think about how this is going to work with real content as multiple scrollbars is never very pretty or easy to use.

Thanks Paul,

I’m now convinced that you never actually sleep!!

Understand that - and the way the application is designed means that it’s only the grey part which will ever overflow. The app runs in a separate browser window, so we don’t have to worry about Toolbars etc taking up space. Obviously the user might reduce the height of the window, but if they go below 768 then that’s their issue, as we have a clearly stated minimum size.

I’ll need to have a look and see what happens in IE6, as some users are definitely still living in that era. So long as it remains usable, I should be ok.

I agree but, hopefully, the users (unless they do something silly with the window) will only ever see one.

Again, thanks for the help - not sure how the world of CSS would function without people like you!!

Nick

I’ll need to have a look and see what happens in IE6, as some users are definitely still living in that era. So long as it remains usable, I should be ok.

If you don’t need the scrollbars on the other areas then IE6 could be made to work like this.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Scrollable 100% high element</title>
<style type="text/css">
* {
    margin: 0;
    padding: 0;
}
p {
    margin: 0 0 1em 0;
}
html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}
.wrap {
    width: 800px;
    margin: auto;
    text-align: left;
    height: 100%;
    overflow:hidden;
}
#outer {
    background: #ffffcc;
    position: absolute;
    width: 800px;
    top: 100px;
    bottom: 20px;
    background: green;
    overflow:hidden;
}
#top {
    position: absolute;
    width: 800px;
    top: 0px;
    height: 100px;
    background: red;
    overflow: hidden;
}
#bottom {
    position: absolute;
    width: 800px;
    height: 20px;
    bottom: 0;
    background: red;
    overflow: hidden;
}
#menu {
    width: 180px;
    background: yellow;
    position:absolute;
    left:0;
    top:0;
    bottom:0;
    z-index:2;
    /*overflow:auto; if you want scrollbars*/
    overflow:hidden;
}
#content {
    background: gray;
    overflow:hidden;
    min-height:0;
    position:relative;
    z-index:1;
}
#midtop {
    height: 200px;
    background: cyan;
    overflow:auto;
    margin:0 0 0 180px;
}
#mid {
    position:absolute;
    top:200px;
    bottom:0;
    left:180px;
    right:0;
    overflow:auto;
    background:teal;
}
</style>
<!--[if lt IE 7]>
<style type="text/css">
html {padding:300px 0 20px} 
#midtop{
    position:absolute;
}
#outer{    
    height:100%;
    position:relative;
        top:auto;
        left:auto;
        bottom:auto;
        right:auto;
        overflow:visible;
}
#mid{
    position:static;
    margin-left:180px;
    background:green;
    zoom:1.0;
    height:100%;
}
#menu {
    top:-200px;
    height:999em;
    bottom:auto;
    z-index:99;
}
#content {
    background:cyan;
    position:absolute;
    height:200px;
    z-index:3;
    top:-200px;
    left:0;
    width:100%;
}

</style>
<![endif]-->
</head>
<body>
<div class="wrap">
    <div id="top">
        <h1> Header</h1>
    </div>
    <div id="outer">
        <div id="menu">
            <p> Menu</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> Menu</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> Menu</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> Menu</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
            <p> test</p>
        </div>
        <div id="content">
            <div id="midtop">
                <p> Top Part goes here</p>
            </div>
        </div>
        <div id="mid">
            <p> start Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part</p>
            <p> Bottom Part end</p>
        </div>
    </div>
    <div id="bottom">
        <p> Bottom</p>
    </div>
</div>
</body>
</html>


Absolutely Ace!

The one remaining IE6 oddity is that there is a scroll bar for the whole window which, if moved, reveals that the “yellow” extends down below the red footer.

I can live with that!

Paul - many, many thanks!

Just hide it in the iE stylesheet.


<!--[if lt IE 7]>
<style type="text/css">
html {padding:300px 0 20px} 
#midtop{
    position:absolute;
}
#outer{    
    height:100%;
    position:relative;
        top:auto;
        left:auto;
        bottom:auto;
        right:auto;
        overflow:visible;
}
#mid{
    position:static;
    margin-left:180px;
    background:green;
    zoom:1.0;
    height:100%;
}
#menu {
    top:-200px;
    height:999em;
    bottom:auto;
    z-index:99;
}
#content {
    background:cyan;
    position:absolute;
    height:200px;
    z-index:3;
    top:-200px;
    left:0;
    width:100%;
}
[B]html,body{overflow:hidden}[/B]
</style>
<![endif]-->


Paul,

That is perfect!!

Thanks for all the help.