Absolute coordinates of DOM element within document
The problem
Sometimes (especially in AJAX projects) it is necessary to get the position of some DOM element in "absolute" coordinates within current document.
For example such "absolute" position is needed if you would like to show some hidden DIV object exactly on the position (or with some offset) of another element. We use this function in our EasyQuery.NET WebForms library to show popup menu under some condition element (you can see an example here).
The solution
Such properties as style.left, style.top or offsetLeft, offsetTop can be use to get (or set) the position of element within its parent. So to get absolute element's position within document we should move upward on element's tree and add the position of all element's parents (except the latest document element).
However it is not quite easy. There are still two problems:
- First, we need to take into account the possible scrolling in element's parent and descrease our result accordingly
- Second, there are some distinctions in beaviour of different browsers (as usual :-( ). For Internet Explorer we always can just substract srolling position of the object stored in element's offsetParent prooperty. But for FireFox we also need to take into considaration all parents accessible by parentNode properties.
var __isFireFox = navigator.userAgent.match(/gecko/i);
//returns the absolute position of some element within document
function GetElementAbsolutePos(element) {
var res = new Object();
res.x = 0; res.y = 0;
if (element !== null) {
res.x = element.offsetLeft;
res.y = element.offsetTop;
var offsetParent = element.offsetParent;
var parentNode = element.parentNode;
while (offsetParent !== null) {
res.x += offsetParent.offsetLeft;
res.y += offsetParent.offsetTop;
if (offsetParent != document.body && offsetParent != document.documentElement) {
res.x -= offsetParent.scrollLeft;
res.y -= offsetParent.scrollTop;
}
//next lines are necessary to support FireFox problem with offsetParent
if (__isFireFox) {
while (offsetParent != parentNode && parentNode !== null) {
res.x -= parentNode.scrollLeft;
res.y -= parentNode.scrollTop;
parentNode = parentNode.parentNode;
}
}
parentNode = offsetParent.parentNode;
offsetParent = offsetParent.offsetParent;
}
}
return res;
}
To use this function just pass your element in parameter and get the result object with left and top coordinates stored in x and y properties accordingly:
var pos = GetElementAbsolutePos(myElement);
window.alert("Element's left: " + pos.x " and top: " + pos.y);
GetElementAbsolutePos function was tested on Internet Explorer 6.0 and higher and FireFox 2.0. We did not do FireFox 3.0 test yet but I think there will no problems with it.

