W3C DOM Compatibility - CSS Object Model View

Last major update on 21 March 2008.

Cover of my book

If you'd like to have some practical examples of what you can do with the W3C DOM, read my book ppk on JavaScript, especially chapter 8.

These compatibility tables detail support for the W3C CSSOM View specification in all modern browsers.

  1. WindowView properties.
  2. ScreenView properties.
  3. DocumentView method.
  4. ElementView properties.
  5. ElementView methods.
  6. Mouse position.

WindowView properties

These properties hold the dimensions of the entire browser window.

Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7
innerWidth and innerHeight
The dimensions of the viewport (interior of the browser window)

Test page
No Yes Yes Yes Yes
window.innerWidth
window.innerHeight
outerWidth and outerHeight
The dimensions of the entire browser window (including taskbars and such)

Test page
No Yes Yes Yes Yes
window.outerWidth
window.outerHeight
pageXOffset and pageYOffset
The amount of pixels the entire pages has been scrolled

Test page
No Yes Yes Yes Yes
window.pageXOffset
window.pageYOffset
screenX and screenY
The position of the browser window on the screen

Test page
No Yes Yes Incorrect Yes
window.screenX
window.screenY
  • Opera calculates the coordinates of the specific tab window relative to the encompassing browser window. This is understandable given its way of working with windows, but strictly speaking it's a bug. It should give the coordinates of the encompassing browser window relative to the screen.
Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7

ScreenView properties

These properties hold information about the screen.

Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7
availWidth and availHeight
The available width and height on the screen (excluding OS taskbars and such)

Test page
Yes Yes Yes Yes Yes
screen.availWidth
screen.availHeight
colorDepth
The color depth (in bits) of the screen

Test page
Yes Yes Incorrect Yes Yes Yes
screen.colorDepth

FF3b4 suddenly gives 24 for my 32-depth screen.

pixelDepth
Same as colorDepth

Test page
No Yes Incorrect Yes Yes Yes
screen.pixelDepth

FF3b4 suddenly gives 24 for my 32-depth screen.

And no, I don't understand why we need a property that contains the same information as colorDepth but isn't supported by IE.

width and height
The width and height of the screen

Test page
Yes Yes Yes Yes Yes
screen.width
screen.height
Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7

DocumentView method

Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7
elementFromPoint()
Returns the element located at the given coordinates

Test page
Yes No Yes Alternative Incorrect and Alternative No
document.elementFromPoint(100,100)

Which coordinates does elementFromPoint() need? IE and Firefox need clientX/Y, while Opera and Safari need pageX/Y. Given the market situation, it's only a matter of time before Opera and Safari change their ways.

  • Opera reports a text node whenever possible, while this method should report the containing element node.

This method is a godsend for drag and drop scripts. When the user drops the dragged element, figure out what element is located at the drop point and go on from there. No more complicated calculations necessary.

However, you need to temporarily hide the dragged object. By definition it's the topmost element on the requested coordinates, and we need to know what's underneath it. The basic trick is:

releaseElement: function(e) { // called onmouseup
	var evt = e || window.event;
	draggedObject.style.display = 'none';
	var receiver = document.elementFromPoint(evt.clientX,evt.clientY);
	draggedObject.style.display = '';
	

Now receiver contains the element the user dropped the dragged element on.

ElementView methods

A few methods that give information about the element.

Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7
getBoundingClientRect()
Gets the encompassing rectangle

Test page
Yes No Almost No No Yes No
x.getBoundingClientRect()

Returns an object that contains the top, left, right, and bottom (all relative to the top left of the viewport) of the combined rectangle of element x. Essentially, the browser calculates all rectangles (see below getClientRects()), and getBoundingClientRect() returns the lowest (top, left) or highest (bottom, right) values found.

IE handles this correctly, provided you accept its incorrect calculation of the individual rectangles.

  • Firefox doesn't round the top/bottom coordinates.
getClientRects()
Gets the several rectangles of an element

Test page
Incorrect Almost No Almost No No Yes No
x.getClientRects()

Returns a list with Rectangle objects that contain the top, left, right, and bottom (all relative to the top left of the viewport) of the rectangles of element x.

The trick here is, that an inline element such as an <em> contains one rectangle for every inline box (line), and that all these rectangles are returned.

  • IE5-7 returns far too many rectangles for the first test paragraphs. The correct number is 5 (for 5 lines), but IE5.5 returns 9 and IE6/7 14. IE8b1 gets this right.
  • Furthermore, IE5-7 also split up a block-level element such as a <p> into one rectangle per line. This is incorrect: a block-level element should be reported as one rectangle.
  • Finally, in all IE versions the rectangles are off by about two pixels. According to John Resig this is caused by the (invisible, but nonetheless present) borders of the <html> element.
  • Firefox doesn't round the top/bottom coordinates.
scrollIntoView()

Makes an element scroll into view

(Not part of the specification)



Test page
Yes Yes Yes Yes No
x.scrollIntoView()

Element x scrolls into view.

Essentially element x behaves as if it's the target of an #hash: it scrolls to the topmost, leftmost position allowed.

Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7

ElementView properties

These properties give information about the dimensions of an Element node (HTML tag).

Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7
clientLeft and clientTop
The position of the upper left corner of the content field relative to the upper left corner of the entire element (including borders)

Test page
Yes No Yes Yes Yes No
x.clientLeft
x.clientTop
clientWidth and clientHeight
The width and height of the content field, excluding border and scrollbar, but including padding

Test page
Yes Yes Yes Yes Yes
x.clientWidth
x.clientHeight
offsetLeft and offsetTop
The left and top position of the element relative to its offsetParent.

Test page
Incorrect Alternative Yes Yes Yes Yes
x.offsetLeft
x.offsetTop
  • When calculating offsetTop, IE7- does not count elements with position: relative as offsetParents, and moves on to the next offsetParent in the chain. offsetLeft is calculated correctly.
  • IE8b1 obeys the offsetLeft/Top rules as long as you accept its odd offsetParent calculation (see below). I expect that once offsetParent is calculated correctly, offsetLeft/Top will be correct, too.
Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7
offsetParent
The ancestor element relative to which the offsetLeft/Top are calculated.

Test page
Yes Buggy Yes Yes Yes Yes
x.offsetParent

When calculating the offsetParent of x the browser moves up the DOM tree to x's ancestors until it encounters one of the following elements. That element becomes x's offsetParent.

  • <body>
  • An element with a position other than static.
  • A <table>, <th> or <td>, but only if x has position: static.

The <body> element does not have an offsetParent. Nonetheless the <html> element sometimes enters the offsetParent chain, though never as the offsetParent of the <body>.

In IE and Opera elements with position: fixed do not have an offsetParent.

  • IE8b1 is confused. Inline elements and table elements never have an offsetParent, it doesn't obey the third rule, and any block level element seems to count as an offsetParent.
offsetWidth and offsetHeight
The width and height of the entire element, including borders

Test page
Yes Yes Yes Yes Yes
x.offsetWidth
x.offsetHeight
scrollLeft and scrollTop
The amount of pixels the element has scrolled. Read/write.

Test page
Yes No Yes Yes Yes Yes
x.scrollLeft
x.scrollTop
x.scrollTop = 20
scrollWidth and scrollHeight
The width and height of the entire content field, including those parts that are currently hidden. (Another way of saying the same: it's the width and height the element would have if it had width: auto; height: auto;.)
If there's no hidden content it should be equal to clientX/Y.

Test page
Incorrect Buggy Yes Yes Incorrect Yes
x.scrollWidth
x.scrollHeight

When you scroll the element all the way down, scrollHeight should be equal to scrollTop + clientHeight.

If the element has no scrollbars scrollWidth/Height should be equal to clientWidth/Height.

  • When the element has no scrollbars IE makes the scrollHeight equal to the actual height of the content; and not the height of the element. scrollWidth is correct.
  • IE8b1 is totally off track. scrollWidth/Height is equal to offsetWidth/Height.
  • Opera doesn't include the element's padding.
Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7

Mouse position

Calculating the mouse position (relative to what?) used to be a JavaScript disaster area. Fortunately the browsers are getting their act together.

Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7
clientX,clientY
window

Test page
Yes Yes Yes Yes Yes
event.clientX
event.clientY

Returns the mouse coordinates relative to the window.

offsetX, offsetY
target

Test page
Buggy pageX/Y No Incorrect Incorrect Incorrect
event.offsetX
event.offsetY

Returns the mouse coordinates relative to the event's target.

But exactly which point in the box serves as a reference point? The spec says the top/left of the padding box, but Opera uses the top/left of the content box, and Safari and Konqueror the top/left of the border box. A nice conundrum. For the moment I'm sticking to the spec.

  • In IE 5-7, the coordinates are calculated relative to the target element when that element is eligible to become an offsetParent. If that's not the case, the coordinates are calculated relative to the target's offsetParent.

    Bug: When the element found by this rule has position: relative, IE moves on to the next offsetParent for the calculation of offsetY, but not of offsetX.

    (Yes, read this twice. It's complicated.)
  • In IE8 offsetX/Y seems to hold the values you'd expect from pageX/Y (minus the <html> border value; see getClientRects() above).
Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7
pageX, pageY
document

Test page
No Yes Yes Yes Yes
event.pageX
event.pageY

Returns the mouse coordinates relative to the document. Most of the time this is the information you want. In order to get it in IE, too, add the scrolling offset of the document to clientX/Y.

screenX, screenY
screen

Test page
Yes Yes Yes Yes Yes
event.screenX
event.screenY

Returns the mouse coordinates relative to the screen.

x, y
Equal to clientX/Y

Test page
Yes No Yes Yes Yes

Nobody can explain why we need x/y when we have clientX/Y. Mozilla's take on this property pair is by far the sanest.

Event IE 5.5 IE 6 IE 7 IE8b1 FF 2 FF 3b5 Saf 3.0 Win Saf 3.1 Win Opera 9.26 Opera 9.5b Konqueror 3.5.7