Table of Contents
Compute Element Location
qx.bom.element.Location .
Often one is interested in the exact location of a DOM element inside a document. At first, it does not seem too hard to compute this information, because following the usual DOM specifications it appears to boil down to a simple calculation of the elements offsets. Well, that is theory...
Digging deeper
In fact, as (way too) often in web development, there exist a lot of incompabilities, pseudo-compatibilities and heavy bugs under across the browser implementations. Even simple properties like offsetTop or offsetLeft return different values for different client engines. This makes it almost impossible to write cross-browser code in this area.
Microsoft’s Internet Explorer offers a non-standard function called getBoundingClientRect() (MSDN Reference), which returns the fully computed location. Without a lot of custom code trying to compute this using JavaScript.
In Mozilla’s Gecko exists a method getBoxObjectFor() (XULPlanet) , which is often used similar to IE‘s getBoundingClientRect(). However, this method unintentionelly lurks on ''nsIDOMNSDocument''. It contains a lot of stuff which is not useful for HTML documents and the developers recommend not to use this rather internal, not-public-API method.
Unfortunately, there is no standardized method to compute the position of a DOM element. This leads to more or less complete implementations in JavaScript libraries, which try to hide the various browser issues underneath a common interface for the web developer.
Known engine bugs
- Mozilla and IE do not take the parent’s element borders into account
- Mozilla does not include the border of the body, if an element isn’t positioned
absoluteand is without anabsolutepositioned parent - IE does not include the border of the body, if an element is positioned
staticand without anabsoluteorrelativeparent - Mozilla does not add the border of a parent that has overflow set to anything but
visible - Safari and Opera include border on positioned parents
- Safari and IE in Standards Mode don’t add the body margin for elments positioned
staticorrelative - Mozilla does not include the border of the body, if an element isn’t positioned
absoluteand is without anabsoluteparent - Opera has a bad scroll value for all TR elements
- IE inserts the (2,2) offset in standards mode, not quirks mode. It’s easy to work around: it sets
document.documentElement.clientLeftanddocument.documentElement.clientTopto 2 in standards mode, or 0 in quirks mode. - CSSOM (CSS Object Model) project want to standardize
getBoundingClientRect.
Framework implementations
- YUI (as of 2.2.2) has an implementation which seems to work quite well
- jQuery (as of 1.1.3) has a method
offset(), which has a lot of workarounds for commonly known bugs of Mozilla, Opera and Safari. - ExtJS (as of 1.0.1) uses an implementation based on YUI’s original code including fixes for Safari and Firefox. (Bug report in Forum
- Dojo’s method (as of 0.9 beta) seems to be work in progress (following the code comments)
- Mochikit has a method
cumulativeOffset(), which provides an offset calculation for all browsers, but without any fixes and workarounds. - Mootools has a method
getPosition()(Element.Dimension) which is comparable to Mochikit’s version. - Tibco contains an implementation respecting simple browser differences, but does not seem to contain support for Opera or Safari.
- GWT uses
getBoxObjectFor()for newer geckos and an offset calculation for older ones. (bug report 634) (See also matching gecko change Bug 330619) - Prototype, Scriptaclous, Base2 do not include an implementation for element position
How to solve the issue
- Do not use
getBoxObjectFor()for gecko-based clients - Use of
getBoundingClientRect()which works quite well in IE and Gecko 1.9, and has less bugs than the offset calculation in these browsers.
An early preview can be seen in the current trunk. This works well for:
- Gecko 1.8 + Gecko 1.9 (Firefox 2.x and Firefox 3.x alpha)
- Internet Explorer 6 + 7
- Safari 3.0 beta
- Opera 9.2
Demos
There are comprehensive examples available in the demobrowser. Remember that this is the devel (not the latest stable) version, so the other examples or the demobrowser application may not always work as expected.
- Open the demo browser with the first location example
- Try the other location samples as well by double-clicking
Location_1_std,Location_2andLocation_2_std - You can open each example in a separate window clicking the “yellow arrow” button in the toolbar
