Main Page Content
Document Body Doctype Switching And More
Six months ago
target="_blank" title="To Dr. Unclear's Netscape 6 tests">a reader of my site alerted me to an important bit of data: when usinga doctype that switches Explorer 6 to Compatibility Mode, several properties ofdocument.body
are reassigned to document.documentElement
. Thisinformation enabled me to get target="_blank" title="Sticky Menu script">one of my scriptsworking in Explorer 6 with a doctype.At first I thought that all properties of document.body
were
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 onlyskimmed through the W3C Recommendations and Flanagan's "JavaScript, the Definitive Guide"to get a theoretical overview. I postponed the necessary browser tests, because they werelikely to be complex and time-consuming.Theory
The overall picture that emerged was as follows:
document.documentElement
has been target="_blank">standardized by W3C as a kind of shortcut to the HTML element, thehighest element in the DOM tree of any (X)HTML page. W3C has not defined any propertiesfor this element.document.body
has been added by Microsoft. Originally it was a convenienceobject that had several properties with information about the current state of the browserwindow and the document in it. Microsoft defined lots of properties, the most important ofwhich areclientWidth
andclientHeight
which store the currentsize of the browser window. It also has propertieslikedocument.body.text
, accessing the old TEXT attribute. It thus (also) refersto the BODY element.
Netscape 6, Explorer 5 and Konqueror have adopted documentElement
as part
body
was originally Explorer-only, but more recentlyboth 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,
body
refers to its only child box: the BODY element. Through their propertieswe 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 likeclientWidth
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 leaveany 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 dodocument.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 officialW3C way to read out this information. (Should there be one? At the moment I don'tthink so. But feel free to disagree.)Fortunately the browser vendors have created their own properties: Netscape 4 and up supports window.innerWidth/
document.body.clientWidth/Height
. All this works fine, though withoutthe blessing of W3C.Doctype switching
When Explorer 6 added the possibility of entering strict standards compliance mode by using
title="To the MSDN explanation of doctype switching. This link works at the moment of writing, but no doubt in a few months this page wil lhave been moved" target="_blank">certain doctypes, it turned out that using these doctypes also influencedthe value of some of these properties. As far as I know this happens only in Explorer 6 on Windows, I haven'tyet found a trace of doctype-switching effects on JavaScript propertiesin 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'slist cause the same compatibility mode. (Here, too, I stand ready to becorrected 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'tsupportdocumentElement
at all.There were no differences between bothMac 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 bethat 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 target="_blank">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:This seems to explain the values I found, so I think he's right.
A few more interesting points:
- Above I said
document.body
is supposed to represent the BODY element, whiledocument.documentElement
should represent the HTML element. This turned out only to bethe case with theoffset
properties in Mozilla and thescrollWidth/Height
propertiesin 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
offset
properties. WhileoffsetHeight
gives the height of the entire HTML document (as it does in mostother browsers),offsetWidth
gives the width of the window, not of theHTML document. - The only reliable property pair is
scrollTop/Left
: it always gives the amountof 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.0on Windows these properties were assigned to bothbody
anddocumentElement
.I wish Explorer 6 had done the same regardless of doctype, it would spare me the need to rewritescripts. - I have been unable to find out what function the
scrollLeft/Top
property pairhas 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 compatibilitymode:Scrolling offset
The scrolling offset of the page is reflected in document.body.scrollTop/Left
,
document.documentElement.scrollTop/Left
. Opera is unreliable here. Fortunately theold Netscape properties window.pageXOffset/pageYOffset
still work in all Netscapesand 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
,
document.documentElement.clientWidth/Height
. Opera is unreliable here, the windowheight is never less than the height of the HTML document. Fortunately theold Netscape properties window.innerWidth/Height
still work in all Netscapesand 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
offsetWidth/Height
gives access to the window width including the scrollbars.Conclusion
The conclusion must be that the implementation of the body/documentElement
I hope my target="_blank">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.