Main Page Content
document.body, doctype switching, and more
Rated 3.68 (Ratings: 6) (Add your rating)
Log in to add a comment
(14 comments so far)
Six months ago
a reader of my site alerted me to an important bit of data: when using
a doctype that switches Explorer 6 to Compatibility Mode, several properties of
document.body are reassigned to document.documentElement. This
information enabled me to get
one of my scripts
working in Explorer 6 with a doctype.
At first I thought that all properties of document.body were
reassigned to document.documentElement, but this turned out not to be the case.
Because the data confused me and because I had other things to do, I only
skimmed through the W3C Recommendations and Flanagan's "JavaScript, the Definitive Guide"
to get a theoretical overview. I postponed the necessary browser tests, because they were
likely to be complex and time-consuming.
Theory
The overall picture that emerged was as follows:
document.documentElementhas been standardized by W3C as a kind of shortcut to the HTML element, the highest element in the DOM tree of any (X)HTML page. W3C has not defined any properties for this element.document.bodyhas been added by Microsoft. Originally it was a convenience object that had several properties with information about the current state of the browser window and the document in it. Microsoft defined lots of properties, the most important of which areclientWidthandclientHeightwhich store the current size of the browser window. It also has properties likedocument.body.text, accessing the old TEXT attribute. It thus (also) refers to the BODY element.
Netscape 6, Explorer 5 and Konqueror have adopted documentElement as part
of their W3C DOM support. body was originally Explorer-only, but more recently
both Netscape 6 and Opera 6 have started supporting it (Konqueror not tested).
So documentElement refers to the outermost box in a document, the HTML element,
while body refers to its only child box: the BODY element. Through their properties
we can read out information about the two most important elements.
-------------- | HTML | |------------| || BODY || || || || || || || || || |------------| --------------
Unfortunately my tests have proven this theoretical model to be unfounded when applied
to properties like clientWidth and offsetHeight.
Besides there is a third box that needs to be measured: the browser window itself. It is frequently far smaller than the HTML document it contains. The theoretical model described above doesn't leave any room for the window dimensions; nonetheless they are present.
No standards
What we want is to read out interesting information about the entire HTML page and the browser window. One of the problems is that the properties that contain this information are not standardized. In the W3C DOM, to read out the total height of the HTML document you'd have to do
document.defaultView.getComputedStyle(document.documentElement,null).getPropertyValue("height")
Apart from the syntax being way too complicated, this only works in Mozilla. It's even worse if you want to know the window width and height or the scrolling offset: there is no official W3C way to read out this information. (Should there be one? At the moment I don't think so. But feel free to disagree.)
Fortunately the browser vendors have created their own properties: Netscape 4 and up supports window.innerWidth/<wbr>Height
and Explorer 4 and up supports document.body.clientWidth/<wbr>Height. All this works fine, though without
the blessing of W3C.
Doctype switching
When Explorer 6 added the possibility of entering strict standards compliance mode by using certain doctypes, it turned out that using these doctypes also influenced the value of some of these properties. As far as I know this happens only in Explorer 6 on Windows, I haven't yet found a trace of doctype-switching effects on JavaScript properties in Mozilla and Explorer on Mac. (But I stand ready to be corrected)
So what exactly happens? I wondered for six months, then finally found the time to do some browser tests.
The experiment
So I set up an experiment. I researched four property pairs, all of which may be properties of
document.body and document.documentElement. The pairs are:
- clientWidth, clientHeight
- offsetWidth, offsetHeight
- scrollWidth, scrollHeight
- scrollTop, scrollLeft
I created two test pages which print out the values of these properties. They are exactly the same, except that I added the doctype
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">
to one of them. It causes Explorer 6 to enter compatibility mode. I chose this doctype more or less randomly. For the moment I assume that all doctypes in Microsoft's list cause the same compatibility mode. (Here, too, I stand ready to be corrected in case anyone has noticed a difference).
View the test pages for yourself, if you like.
I tested the various properties in several browsers: Explorer 5.0 and 6.0 on Windows, Explorer
5.0 on Mac OS 9 and 5.1 on OS X, and Mozilla 1.0 final. I also studied Opera 6, which doesn't
support documentElement at all.
There were no differences between both
Mac Explorers, only very slight differences between the Windows Explorers on the no-doctype page.
The actual testing consisted of carefully measuring the various widths and heights and finding out which properties contained these numbers.
No general rules
I'd hoped to find some general rules for dealing with document.body,
document.documentElement and doctype switching. Unfortunately the conclusion must be
that there are considerable differences between body and documentElement
and that a lot happens in Explorer 6 when switching between quirks and standards mode,
but that it is impossible to formulate a general theory.
See the table of research results and try to make sense of it. I can't. If you do find a general rule, please note it in a comment below.
One rule concerning Explorer 6 in Strict mode has been made clear by Michael van Ouwekerk of 13th Parallel. He wrote:
From what I've gathered so far, IE6 in Strict mode always makes the html element as big as the viewport. The styles given by currentStyle are width: auto, height: auto, overflow: scroll. The offsetWidth and offsetHeight are always equal to the viewport's width and height. When there is a lot of content, the overflow: scroll takes care of that.This seems to explain the values I found, so I think he's right.
A few more interesting points:
- Above I said
document.bodyis supposed to represent the BODY element, whiledocument.documentElementshould represent the HTML element. This turned out only to be the case with theoffsetproperties in Mozilla and thescrollWidth/Heightproperties in Explorer 6 in standards compliance mode. Otherwise this theory has little to do with practice. - Explorer 5 on Mac and Opera 6 are inconsistent in their use of the
offsetproperties. WhileoffsetHeightgives the height of the entire HTML document (as it does in most other browsers),offsetWidthgives the width of the window, not of the HTML document. - The only reliable property pair is
scrollTop/Left: it always gives the amount of pixels the page has scrolled. Unfortunately this information is highly doctype-sensitive: in standards compliance mode in Explorer 6 these properties belong todocumentElement, while in quirks mode they belong tobody, just like in all other browsers. In Explorer 5.0 on Windows these properties were assigned to bothbodyanddocumentElement. I wish Explorer 6 had done the same regardless of doctype, it would spare me the need to rewrite scripts. - I have been unable to find out what function the
scrollLeft/Topproperty pair has in Opera 6. The values simply don't make sense.
Practice
So how do you write cross-browser scripts that avoid all these complications? Here are some examples that survive using a doctype that switches Explorer 6 to compatibility mode:
Scrolling offset
The scrolling offset of the page is reflected in document.body.scrollTop/Left,
except when you use a doctype in Explorer 6, then it is reflected in
document.documentElement.scrollTop/Left. Opera is unreliable here. Fortunately the
old Netscape properties window.pageXOffset/pageYOffset still work in all Netscapes
and Opera. So the script would become:
if (window.pageYOffset)
{
pos = window.pageYOffset
}
else if (document.documentElement && document.documentElement.scrollTop)
{
pos = document.documentElement.scrollTop
}
else if (document.body)
{
pos = document.body.scrollTop
}
and pos contains the vertical scrolling offset.
Window dimensions
The window dimensions are reflected in document.body.clientWidth/Height,
except when you use a doctype in Explorer 6, then they are reflected in
document.documentElement.clientWidth/Height. Opera is unreliable here, the window
height is never less than the height of the HTML document. Fortunately the
old Netscape properties window.innerWidth/Height still work in all Netscapes
and Opera. So the script would become:
if (window.innerWidth)
{
theWidth = window.innerWidth
}
else if (document.documentElement && document.documentElement.clientWidth)
{
theWidth = document.documentElement.clientWidth
}
else if (document.body)
{
theWidth = document.body.clientWidth
}
and theWidth contains the width of the window. Note that the clientWidth is always
the width excluding the scrollbars. Generally (but not always),
offsetWidth/Height gives access to the window width including the scrollbars.
Conclusion
The conclusion must be that the implementation of the body/documentElement
properties in the various browsers, with and without doctypes, is very complicated. I can find no overall
theoretical model that explains what the four property pairs are for and what the effect of a
doctype switch is.
I hope my table of research results will allow people to formulate theories. If you think you understand the behaviour of a certain browser (or, better yet, all browsers), please leave a comment below.



