I want to know how to get the X and Y position of HTML elements such as img
and div
in JavaScript relative to the browser window.
I've taken @meouw's answer, added in the clientLeft that allows for the border, and then created three versions:
getAbsoluteOffsetFromBody - similar to @meouw's, this gets the absolute position relative to the body or html element of the document (depending on quirks mode)
getAbsoluteOffsetFromGivenElement - returns the absolute position relative to the given element (relativeEl). Note that the given element must contain the element el, or this will behave the same as getAbsoluteOffsetFromBody. This is useful if you have two elements contained within another (known) element (optionally several nodes up the node tree) and want to make them the same position.
getAbsoluteOffsetFromRelative - returns the absolute position relative to the first parent element with position: relative. This is similar to getAbsoluteOffsetFromGivenElement, for the same reason but will only go as far as the first matching element.
getAbsoluteOffsetFromBody = function( el )
{ // finds the offset of el from the body or html element
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
{
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
getAbsoluteOffsetFromGivenElement = function( el, relativeEl )
{ // finds the offset of el from relativeEl
var _x = 0;
var _y = 0;
while( el && el != relativeEl && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
{
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
getAbsoluteOffsetFromRelative = function( el )
{ // finds the offset of el from the first parent with position: relative
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
{
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
if (el != null)
{
if (getComputedStyle !== 'undefined')
valString = getComputedStyle(el, null).getPropertyValue('position');
else
valString = el.currentStyle['position'];
if (valString === "relative")
el = null;
}
}
return { top: _y, left: _x };
}
If you are still having problems, particularly relating to scrolling, you could try looking at http://www.greywyvern.com/?post=331 - I noticed at least one piece of questionable code in getStyle which should be fine assuming browsers behave, but haven't tested the rest at all.