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:
html
body
html
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
.