W3C DOM Compatibility - CSS Object Model View

Last major update on 29 March 2009.

Mobile table.

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 and ElementView methods.
  4. ElementView properties.
  5. Mouse position.

WindowView properties

These properties hold the dimensions of the entire browser window.

Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a Konqueror 3.5.7
innerWidth and innerHeight
The dimensions of the viewport (interior of the browser window)

Test page
No Yes 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 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 Yes
window.pageXOffset
window.pageYOffset
screenX and screenY
The position of the browser window on the screen

Test page
No Yes 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.
Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a Konqueror 3.5.7

ScreenView properties

These properties hold information about the screen.

Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a 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 Yes
screen.availWidth
screen.availHeight
colorDepth
The color depth (in bits) of the screen

Test page
Yes Yes Yes Yes Yes Yes
screen.colorDepth
pixelDepth
Same as colorDepth

Test page
No Yes Yes Yes Yes Yes
screen.pixelDepth

The difference between colorDepth and pixelDepth is only important on (older?) Unix machines, where old X-clients may allow applications to define their own color scheme. If that’s the case, colorDepth matches the color depth of the application and pixelDepth the color depth of the monitor. In all other cases they’re equal.

width and height
The width and height of the screen

Test page
Yes Yes Yes Yes Yes Yes
screen.width
screen.height
Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a Konqueror 3.5.7

DocumentView and ElementView methods

Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a Konqueror 3.5.7
elementFromPoint()
Returns the element located at the given coordinates

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

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

  • Opera 9 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);
	if (receiver.nodeType == 3) { // Opera
		receiver = receiver.parentNode;
	}
	draggedObject.style.display = '';
	

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

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
Buggy Yes 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. IE8b2 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 IE 5-7 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 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.

  • Safari iPhone handles the Y-coordinate correctly, but it also scrolls to the left edge of the page, which can make this method hard to use when the user has zoomed in.
Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a Konqueror 3.5.7

ElementView properties

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

Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a 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 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 Yes
x.clientWidth
x.clientHeight
offsetLeft and offsetTop
The left and top position of the element relative to its offsetParent.

Test page
Incorrect Yes Yes Yes Yes Yes Yes
x.offsetLeft
x.offsetTop
  • When calculating offsetTop, IE5-7 does not count elements with position: relative as offsetParents, and moves on to the next offsetParent in the chain. offsetLeft is calculated correctly.
Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a Konqueror 3.5.7
offsetParent
The ancestor element relative to which the offsetLeft/Top are calculated.

Test page
Yes Yes 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.

offsetWidth and offsetHeight
The width and height of the entire element, including borders

Test page
Yes 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 Yes 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.
If there's no hidden content it should be equal to clientX/Y.

Test page
Incorrect Yes Yes 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, except in IE8, where it’s 5 pixels off.
  • Opera gives odd, incorrect values.
Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a 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.

Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a Konqueror 3.5.7
clientX,clientY
window

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

Returns the mouse coordinates relative to the window.

On the iPhone this pair returns the same values as pageX/Y. That makes sense: on the iPhone the screen area is the same as the window area is the same as the document area.

offsetX, offsetY
target

Relative to the top/left of the padding box.



Test page
Buggy Yes No border box border box content box border box
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 (i.e. the box formed by content and padding, but excluding the border). IE8 is the only browser to get this right.

  • In IE 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.)
Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a Konqueror 3.5.7
pageX, pageY
document

Test page
No Yes 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 Yes
event.screenX
event.screenY

Returns the mouse coordinates relative to the screen.

On the iPhone this is almost equal to pageX/Y, though there’s usually a difference of 1 or 2 pixels. The equality makes sense: on the iPhone the screen area is the same as the window area is the same as the document area.

x, y
Equal to clientX/Y

Test page
Yes page X/Y No Yes Yes Yes Yes

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

Selector IE 5.5 IE 6 IE 7 IE8 as IE7 IE8 as IE8 FF 2 FF 3.0 FF 3.1b Saf 3.0 Win Saf 3.1 Win Saf 4.0b Win Chrome 1 Chrome 2 Opera 9.62 Opera 10a Konqueror 3.5.7

These compatibility tables are sponsored by

Google