A bulletproof way to create a div with height = viewport height? also something weird

i just want to find a way to use CSS to create a div that is 100% of the viewport’s height… and something weird, why both <html> and <body> has to have height: 100% and why not just one of them?

http://www.0011.com/css-test/div_test

code:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
 
 
	<head> 
 
		<title> 
			div
		</title> 
		
		<style type="text/css">
			body, html { height:100%; background:#ffc }
			p { background: #ddd }  
			#divFirst { height:100%; background: yellow }
			
		</style>		
		
	</head> 
	
	<body> 
	
		<div id="divFirst">hi</div>
		
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
	
		<p> 
		    <a href="http://validator.w3.org/check?uri=referer"><img

		        src="http://www.w3.org/Icons/valid-html401"

		        alt="Valid HTML 4.01 Strict" height="31" width="88" style="border:none"></a> 
 
		    <a href="http://jigsaw.w3.org/css-validator/check/referer"> 
		        <img style="border:0;width:88px;height:31px"

		            src="http://jigsaw.w3.org/css-validator/images/vcss"

		            alt="Valid CSS!"> 
		    </a> 
		</p> 
			   

also weird is that the background color #ffc goes all the way to the end of document, so that means the body goes all the way to the end of the document… so why does the first div not go all the way, since its height is 100% of containing element, which is <body>?

also, if the line

body, html { height:100%; background:#ffc }

is changed to 60%, then FF and Chrome both show a 36% height div, while IE 7 shows a 60% div… what is the rule here? I think these questions may need a guru to answer them… thanks.

I think these questions may need a guru to answer them… thanks.

That I am not, and don’t know what the browsers are trying to do when the height isn’t 100%.

Also, to be safe in the real world, you’ll likely always want to make that 100% child div into min-height: 100% (and then just height for IE6).

and something weird, why both <html> and <body> has to have height: 100% and why not just one of them?

Try this:

an empty page, with just the html element, body, and a single div with something trivial in it (the body isn’t allowed to be empty re the specs).

If you give the html element a background colour, you’ll see it always fills the viewport.

If you then also try to give the body a background-color, you’ll get only that colour around any content in the page (our trivial div).

So first this:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta http-equiv="content-language" content="en">
    <title>A title</title>
    <meta name="description" content="blah">
    <style type="text/css">
* {
  margin: 0;
  padding: 0;
}
html {
  background-color: #f00;
}

body {
  background: #ff0;
}

    </style>
  </head>
<body>
<div>!</div>
</body>
</html>

Now, change the body’s declaration to a background image.


html {
  background-color: #f00;
}

body {
  background: #ff0 [b]url(sheepdog2.png)[/b];
}

The bg image also only goes where the content is (I have that image, of course use one you actually have). So same as before-- the body is sticking to the content instead of filling the viewport, simply because we have mentioned the existance of the html element.

Now, remove any mention of the html element.

Suddenly, the body now seems to take the place of the html element-- it expands to fill the viewport irregardless of content.

So I always thought the only reason we even mention the html element was for IE, but apparently I was wrong.

Since the html element is the root, the Ultimate Parent of Truth, Justice and the Communist Way, it seems we must give an explicit height to both the html AND the body elements, before the single child can use that as a basis for being 100% high.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html lang="nl">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta http-equiv="content-language" content="nl">
    <title></title>
    <meta name="description" content="something">
    <!--link rel="stylesheet" type="text/css" href="#"-->
    <style type="text/css">
* {
  margin: 0;
  padding: 0;
}

body {
  height: 100%;
  background: #ff0 url(sheepdog2.png);
}

body div {
  height: 100%;
  background-color: #0cea06;
}

    </style>
  </head>
<body>
<div>!<br>
!<br>
!</div>
</body>
</html>

With only the body being mentioned, the div cannot be 100% high, even though clearly (from my bg image) the body is filling the viewport and I’ve given it an explicit height.

I’m not a guru, and I’m sure one (Paul, Graeme) will answer why that is, but that’s how it is. But if I add the html element to the height declaration:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html lang="nl">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta http-equiv="content-language" content="nl">
    <title></title>
    <meta name="description" content="something">
    <!--link rel="stylesheet" type="text/css" href="#"-->
    <style type="text/css">
* {
  margin: 0;
  padding: 0;
}

[b]html,[/b] body {
  height: 100%;
  background: #ff0 url(sheepdog2.png);
}

body div {
  height: 100%;
  background-color: #0cea06;
}

    </style>
  </head>
<body>
<div>!<br>
!<br>
!</div>
</body>
</html>

Suddenly every parent has a stated height, so now the child div has something to work with.

As far as I know this is the only exception to the CSS height rule: that you can’t give a child a % height unless it has a parent with an explicit (non%) height. IF both html (ultimate parent) and the body (the div’s direct parent) have a height declared, the div now has something to work with.

Your code:

I’m wondering how you can have something with 100% height, and then add elements after it.

Taking your code, I got a div that was indeed 100% high… of the viewport. But you’re trying to take 100% (100% means all, everything, right?) and adding to it. The only way the browser can deal with that is let the 100% element fill the viewport, and forcing you to scroll down to see the p’s.

Remove the p’s and the div really is 100% high-- it’s everything.

Now try this:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta http-equiv="content-language" content="en">
    <title>ZOMG! Waffles!</title>
    <meta name="description" content="blah">
    <style type="text/css">
* {
  margin: 0;
  padding: 0;
}

html, body {
  height: 100%;
  background: #ff0 url(sheepdog2.png);
}

#divFirst {
  height: 100%;
  background-color: #0cea06;
}

[b]p.first {
  margin-top: -50%;
}[/b]

    </style>
  </head>
<body>
		<div id="divFirst">hi</div>
		
		<p [b]class="first"[/b]>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
		<p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p><p>hello world</p>
	
		<p>
		    <a href="http://validator.w3.org/check?uri=referer"><img

		        src="http://www.w3.org/Icons/valid-html401"

		        alt="Valid HTML 4.01 Strict" height="31" width="88" style="border:none"></a>

		    <a href="http://jigsaw.w3.org/css-validator/check/referer">
		        <img style="border:0;width:88px;height:31px"

		            src="http://jigsaw.w3.org/css-validator/images/vcss"

		            alt="Valid CSS!">
		    </a>
		</p>
</body>
</html>

This brings that first p (and so also everyone else who comes after him) to the same level as the text in divFirst.

Looks pretty cool. This is basically what we do with those sticky footers (except then the p’s would be outside the divFirst container).

Not really the case. If no background is defined for the html, then whatever background is defined for the body will be transferred back to the html instead - a bottom border on the body element will soon show where it really is. A background applied to the html will fill the screen even if the height of the html element (again shown with a bottom border) is set to less than screen height.

The really weird thing is with a background image applied to the body with no background on the html. A non-repeated background image aligned center center on the body will behave a little different between browsers. Firefox calculates the horizontal position from the width and height of the html element, whereas IE calculates the horizontal position from the body width and the html or viewport height, whichever is greater. With only small content, the vertical position of the background image will be very different between IE and FF, and if the body has a width set, the horizontal position is very different when the window is sized.

When both the html and body elements have a percentage height, both those percentages will be relative to the viewport height in IE, and the body height will push the html height if greater, whereas in Firefox the body percentage will be relative to the html percentage height (which seems more logical).

So even with simple things like backgrounds and base percentage heights, cross-browser conformity is still a problem. Haven’t delved into the css specs to try and work out which implementations are closer to the intended (if the specs are even specific in this area), nor have I experimented with Opera or Safari to what their behaviour is.

Hey,
I’m by no means a guru, but this is what I found somewhere when I was looking for this solution. This is apparently a cross-browser solution, although I haven’t been able to check it on a PC yet. But it does work on Mac FF3. Hope it at least helps spur the conversation.


html, body {
height: 100%;
}

* html #page {
height: 100%;
}

div#page {
	min-height: 100%;
}

Yes that is a common technique and is talked about in more detail in the FAQ of this forum.