Some Technical Background
If you set an element’s
height with a percentage value you have to ask yourself, “A percentage of WHAT?” If an element’s height is 50% what is this 50% value based on? The answer is simple: height percent values are based on the height of the element’s containing block. For example, if I set the height of a UL element to 500 pixels and set the height of a child LI element to 10%, that LI will have a height of 50 pixels. The UL is the containing block of the LI.
But if the containing block has no explicit height set, what happens then? Long story short, that percentage value is treated as
auto. You can read all about this in the CSS spec.
Some Design Background
There’s a visual element web designers have been using for years now using different techniques. That is making the layout appear as tall as the viewport even if the content of the page is not tall enough in and of itself to force the layout to that height. Something like this.
The BODY element has a gray background and a DIV with a
min-height value set to 100%. This is the trick I use. If I didn’t use
min-height, but just regular
height then the white box would only be as tall as the viewport and the text would overflow below the white box like this.
So what if I try to nest DIVs with
min-height set to 100%? Well then this happens.
The gray box doesn’t go the full height of the screen. Why?
To The Spec!
Take a look at what the CSS spec has to say on min/max-height, specifically this bit about percentage values:
“Specifies a percentage for determining the used value. The percentage is calculated with respect to the height of the generated box’s containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the percentage value is treated as ‘0’ (for ‘min-height’) or ‘none’ (for ‘max-height’). “
So unless the height of the containing block is explicitly set to a value that doesn’t depend on the height of its content
min-height takes a value of 0.
The containing block in my example has a
min-height value of 100%. The
height of this box depends on the height of its content. That’s because if there’s a lot of content the height will be larger than the minimum height of 100%. The height of the containing block is not set in stone. This is why any child element’s min-height value will be treated as 0.
Thus, the gray box does not extend down to the bottom of the page.
So why is it that if I set a height value of 100% on the BODY and HTML elements the gray background color for the BODY doesn’t end like it does to the DIV with the white background color and a height of 100% in this example?
Actually, it does.
BODY Is Special
The BODY element has a fixed height. It inherits this height from the HTML element which inherits it from the viewport of your web browser. If your web page has content that requires more vertical space than is available, the BODY element’s
overflow property dictates what happens. In this instance the default vaule for the BODY’s
overflow property is
auto. This means scrollbars will be generated as needed so that we can scroll through that content inside the BODY element.
This is an important concept here: even though the contents of the BODY element are taller the height of the BODY element itself will only be as tall as the viewport allows. Put it another way, if your browser window is 500 pixels tall then your BODY element is 500 pixels tall. If the content of the BODY element is 1000 pixels tall, the BODY element’s height is still 500 pixels, but scrollbars are generated that let you scroll through the content of the BODY element 500 pixels at a time.
If I set
overflow:auto on that white box while it has a
height of 100% you’ll see exatly the same thing that’s happening to the BODY in that scrollbars are generated to let you scroll through the content inside the white box.
This is why in this example the white box is only as tall as the window and not as tall as the content. The white box has a height of 100%, but the overflow property of that box takes the default value visible, which means the browser renders all of the content even if it extends beyond the dimensions of the containing block.
Putting It All Together
In my original example both the HTML and BODY elements have a height of 100%. The white box has a
min-height of 100%. Using the rule put down by the CSS spec we can see that the containing block of the white box (the BODY element) has an explicit height (the height of the viewport) and that height value does not rely on the content of its children (it relies on the dimensions of the viewport). Thus the white box will have a minimum height the same as the height of the body. The white box will always be as tall as the window even if the content isn’t tall enough to fill in that space.
The gray box in this example also has a
min-height of 100%, but it’s containing block (the white box) has a height that IS dependant on the height of its children. Therefore the
min-height property of the gray box is treated as having a value of 0, preventing it from taking up the full vertical space of the page (like the white box).
Therefore, a child element whose immediate parent element has a
min-height value set cannot itself have a
min-height value. In other words: no nesting
min-height:100% will only work on an immediate child of the BODY element. It turns out this little CSS trick has a very limited scope. So if you ever use it be sure you understand what you’re getting into.