Experiments:
A pure CSS experiment to determine default behaviour.
The same, but in quirks mode.
The same, but I added the :root selector.
Click on elements. What is the target?
Try interesting properties and see what they mean (or don't mean).
No background for the html element.
Set the heights of some crucial elements.
On this page I discuss some experiments to determine the relation between the viewport and the document inside it, both from a CSS and from a JavaScript point of view.
These experiments are hardly complete, and I'm not entirely sure yet how the results should be interpreted. In deference to Explorer 6 all experiments but one are in Strict Mode.
We take the following simple HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"> <html> <head> <title>The pure effect</title> </head> <body> The BODY <div id="testdiv"> The DIV </div> </body> </html>
and the following CSS:
html,body,div {
position: relative;
margin: 20px;
padding: 0;
font: 13px verdana,helvetica,arial,sans-serif;
border: 1px solid #000000;
}
html {
background-color: #732264;
}
body {
background-color: #B0BDEC;
}
div {
background-color: #DEE7F7;
}
See the pure example in Strict mode and the Quirks mode example. Only Explorer 6 Windows makes any difference between Quirks and Strict mode.
The browsers render it as follows. Opera, Explorer Mac and Safari agree with each other.
html element as small as possible. Since its height
defaults to auto this is completely correct as long as you treat the html element
like any other without dwelling on its special purpose.html element span the entire viewport, though it does honour the 20px margin.
Thus Mozilla sees the html element as a special case which shouldn't quite behave as any other element.html element span the entire viewport, and it refuses
to display the margin. It treats the element as an initial containing block that cannot span anything else
than the viewport. The CSS 100% height experiment confirms this conclusion.margin-bottom of the div go? I have no idea, and for the moment I classify this
behaviour as a bug)body element as the container
for the entire page. It renders the margin of the body as a padding.The next test adds the :root selector to the style sheet.
Note that I defined the :root styles before the normal ones:
<style>
<!--
:root {
border: 1px solid #000000;
background-color: #cccccc;
}
-->
</style>
<link rel="stylesheet" href="doctests.css">
Mozilla, Explorer Mac and Safari support :root: in these browsers :root seems to denote the
same element as html. Not unexpected, and certainly understandable.
The :root style (gray background) overrules the html style (purple background)
because :root is a pseudo-class, which, like a real class, overrules a mere tag name.
:root = html
I'm curious what Opera will do with this pseudo-class. As we'll see later on, it probably inserts another
block between html and the viewport. Will this anonymous block become the :root?
The next experiment confirms this theory. I added an onclick event handler to the document.
Clicking anywhere in the page reveals (should reveal) the target of the click.
Personally I feel that a really consistent implementation would give the
document as the target of a click outside the visual border of the html.
All browsers disagree with me, though.
| Click on | Explorer 6 Windows | Explorer 5.2 Mac | Mozilla 1.6 | Safari 1.2 | Opera 7.50 |
|---|---|---|---|---|---|
|
div
| div | div | div | div | div |
|
body
|
body | body | body | body | body |
|
html
|
html | No reaction | html | body | html |
|
Outside html
|
Not possible | No reaction | html | body | html |
html.
Clicking on an element shows that element as the event target, and clicking outside the html element
is impossible.html element, the event target
is nonetheless html.html reveals the body as
the event target.html element at all.The html element's visual border does not denote its true border.
The area outside it is also part of this element. Therefore, despite appearances, the
html element is not a normal element like any other.
Presentation and behaviour match perfectly only in Explorer Windows.
Let's continue with JavaScript. Is the html element a normal DOM object, to which you can
append children? The next experiment takes a closer look.
I try to append a span to the div, the body, the html element and
the document. You should see a black 50x50 block in the upper left corner of the element.
Then I alert the nodeName of the last child of this element. If my append action succeeds it should be
SPAN.
Note: Explorer Mac and Opera may have redrawing problems. Hide the window and take it forward again to see changes in the layout, if any.
| Append to | Explorer 6 Windows | Explorer 5.2 Mac | Mozilla 1.6 | Safari 1.2 | Opera 7.50 |
|---|---|---|---|---|---|
|
div
|
Yes | Yes | Yes | Doesn't show | Yes |
|
body
|
Yes | Yes | Yes | Doesn't show | Yes |
|
document
|
Doesn't show | Yes | Yes | Error | Yes |
|
document
|
Doesn't show | Action failed | Error | Error | Error |
document element, but it
doesn't append the block either. The alert shows the html element.span but the browser doesn't show the block when I append it to the
html and document elements. It is the only browser to append the block to the
document. There are no differences between Strict and Quirks mode.On the whole I side with Mozilla and Opera here. Although custom dictates that an html element
should only contain a head and a body element, the DOM shouldn't be limited
by HTML custom, since it is meant for working with any XML document. Appending children to the documentElement
should work.
Appending children to the document element is not allowed, though.
Browsers see the document.documentElement as a normal element node to which you can
append children. The document can have only one child, though: document.documentElement.
Let's take it one step further and try to remove document.body and even
document.documentElement from the DOM tree.
Warning: May crash Explorer 5.2 Mac and Safari 1.2. See below.
| Remove | Explorer 6 Windows | Explorer 5.2 Mac | Mozilla 1.6 | Safari 1.2 | Opera 7.50 |
|---|---|---|---|---|---|
|
div
|
Yes | Unstable | Yes | Crash | Yes |
|
body
|
Yes | Unstable | Yes | Crash | Buggy |
|
document
|
Yes | Nothing happens | Keyboard control lost | Yes | Error |
documentElement.documentElement in Mozilla works, but the keyboard no longer controls
the window.html background colour when you tell it to remove the body.Only Explorer Windows does as it's told without raising a fuss.
Removing document.body and
document.documentElement shows fascinating browser behaviour that is impossible
to correlate with other findings.
In the next experiment you can select a property of an element. The script shows a bar that is as wide
or as high as the tested property dictates, and sets it in the upper left corner of the element. So you
can check whether the value of document.body.offsetHeight matches the height of the body.
These experiments are the only ones to have a practical value, because we need this information for cross browser scripts to read out the window height, the document height and the scrolling offset.
See the browser compatibility page for the results.
Safari note: it is the only browser to give the document dimensions. All other browsers
return undefined.
In the next experiment I declared
html {background: transparent;}
In all browsers the html element reverse-inherits the background colour of the
body element. Not surprising, but the test had to be performed.
As we all know all browsers generate a scrollbar when the HTML page is longer (or wider) than the viewport.
In CSS scrollbars are ruled by the overflow declaration. The
next experiment tries to find out whether the normal page scrollbar is also set by an overflow
declaration, and, if so, on which element it is applied. It also tests basic support for overflow
on the body and html elements.
You can set the overflow of html and body to default, visible, hidden
or auto. default means: no overflow value given.
Safari turns out not to support overflow on these elements at all.
Explorer Mac has a bug: when you set overflow: hidden
on the body this style remains in place after a reload. You can overrule it by resetting
overflow: auto.
For the moment I describe five tests:
body and html to overflow: auto.body and html to overflow: hidden.overflow values the browser uses
as default (if any).All "Desired result" screenshots are from Opera, which is by far the most consistent browser in this series of tests.
| Test | Explorer 6 Windows | Explorer 5.2 Mac | Mozilla 1.6 | Safari 1.2 | Opera 7.50 |
|---|---|---|---|---|---|
|
body {overflow: auto}
Generate a scrollbar for the body element only
Desired result |
Almost | No | Yes | Untest |
Yes |
Explorer Windows suddenly gives the div with position: relative a position: fixed.Explorer Mac doesn't react at all: it shows the scrollbar for the entire page. |
|||||
|
html {overflow: auto}
Generate a scrollbar for the html element only
Desired result |
Almost | Hides body | Buggy | Untest |
Yes |
Explorer Windows gives the html element a slightly greater width than before,
probably because the space for the scrollbar is removed. This leads to a horizontal scrollbar.
Mozilla and Opera both move the scrollbar to just inside the border of the html element.
However, Mozilla never restores the scrollbar to its original position.
Mozilla removes the background colour of the body. |
|||||
|
body {overflow: hidden}
Hide content at body border.
Desired result |
Yes | Not quite | Yes | Untest |
Yes |
| Explorer Mac removes the scrollbar of the entire page. | |||||
|
html {overflow: hidden}
Hide content at html border.
Desired result |
Yes | Hides body | Buggy | Untest |
Yes |
Explorer sees the entire viewport as the html element, so although it doesn't
cut off the content at the bottom border of the html (which isn't visible in any case),
it performs this test correctly according to its own definitions.
Mozilla removes the background colour of the body. |
|||||
|
Restore default
option "[no value]" not allowed!
Desired result |
html:auto body:visible |
html:visible body:auto |
Untest |
Untest |
html:visible body:visible |
Setting both elements to overflow: visible seems to be the cross-browser way,
The test only works in Mozilla 1.6 if you haven't made any changes yet. However, this kind of defeats the purpose of the test. Explorer Windows never quite restores the defaults. |
|||||
overflow of the html
element to hidden or auto causes two bugs:
body background disappears.html {overflow}.overflow: auto does not react to the mouse wheel, it can only be scrolled by dragging
the scrollbar. Using the mouse wheel is only possible when scrolling the entire page.html {overflow: auto}, the html element cannot be scrolled by the wheel
in Opera, but it can in Mozilla! This means that in Mozilla the html element is
the initial containing block. Opera inserts one more block between html and viewport, and this
block (and not the html element) can be scrolled by the mouse wheel.html {overflow: auto} the html
scrollbar (which is the page scrollbar) is permanently moved to its position just inside the
border of the html element. You cannot return it to its default position in any way (except by
reloading the page, of course). That's why it has Almost instead of Yes on a few tests.body element as the initial containing block, even though its
behaviour is inconsistent.html {overflow: auto}
test. Therefore returning to the default situation is not really possible.Based on these tests, browsers define their initial containing block as follows:
htmlbodyhtml and viewportdocument
element dimensions (see Properties experiment), I suspect it also inserts an extra element. This conclusion is
less certain that the ones above, though.Opera is the most consistent browser in this series of tests.
The last experiment allows you to
set the heights of the documentElement, the body and the div
to auto, 300px, 50% and 100%.
I need expert help from a CSS guru to interpret the results, so I don't draw any conclusions yet.
Try it for yourself and see what you think.
If you want to seriously delve into this subject, please write a page about the results of the experiment in several browsers and tell me when it's online. I'll link to you.
I cannot yet draw real conclusions; my experiments have hardly started yet. Nonetheless there seem to be some general rules:
html as a special element, not as just any block
level element. It always spans the entire viewport, even though it may not seem to. Opera and Safari
treat it as any block level element when it comes to CSS, but not in JavaScript.body and the rest of the page. This new block level element became the body,
and its parent (the old body) became the html element. It retained most of its
properties and behaviour, though.body and html.