Forum Moderators: open
Is there any way I can find the x and y coordinates of an HTML element that's positioned relatively on a page?
Unfortunately, both offsetLeft and offsetTop do not account for border widths. I solved that problem by building my div elements using DOM and specifying the width of each border by doing el.style.borderWidth = 'Xpx'; where X is a number of your choice (hope this helps someone out there).
In my function that captures the X and Y coords, I'm using el.parentNode.style.borderLeftWidth for the x coordinate and el.parentNode.style.borderTopWidth for the y coordinate and I'm adding those values to el.parentNode.offsetLeft for x and el.parentNode.offsetTop for y coordinate.
Everything works fine when all my HTML elements on the page have a position of absolute. However, as soon as a parent element's position turns relative, the coordinates returned are no longer accurate.
I've been reading that FireFox has a built-in API as of version 3.5 called el.getBoundingClientRect().
This is a major problem on the web for many users so if I find anything, I'll post it here but if anyone knows of any ways, I would gladly appreciate a hint or direction.
Thanks!
Bobby
function getElementPosition(el) {
var l = 0, t = 0;
while (el.offsetParent) {
l += el.offsetLeft;
t += el.offsetTop;
el = el.offsetParent;
}
return {left:l, top:t};
}//example (pass an element reference):
var pos = getElementPosition(element);
var s = 'element\'s left coordinate on the page is: '+ pos.left;
s += '\nelement\'s top coordinate on the page is: '+ pos.top;
alert(s);
That is, let's say you have a DIV centered on the page, border 10px all around. Inside that, you have another DIV text-aligned right, border 5px:
<div style="border:10px solid black;text-align:right;">
<div>foo</div>
</div>
Where does the error occur? When you hover your mouse over the border, or is it reporting the wrong offset from the parent?
Vol7ron: I should have provided code for this. My problem is that I'm seeing the wrong results rather than getting an error.
So, I have a code that you can run and see what I'm trying to achieve. Let's stick to Firefox for now as our browser. Please note that the div element I have has 'position:absolute' applied with no padding and margin size of 10px. This also includes the body and html elements both having a position of absolute value but no margin and padding.
One last thing to note is that I have a "p" element specified after the "div" element. If you run this code in your browser, you'll notice a "10, 10" will be returned and both the left offset and top offset is of equal distance from the edge of the browser window. So far so good and I would expect that as my result.
<html>
<head>
<style type="text/css">
html,body{
position:absolute;
height:100%;width:100%;
padding:0px; margin:0px;
}
div {
position:absolute;
height:100px; width:100px;
padding:0px; margin:10px;
border: 1px dotted #000000;
}
</style>
</head>
<body>
<div id="d0"></div>
<p id="result"></p>
<script type="text/javascript">
function getXY(el) {
var x = 0;
var y = 0;
x += el.offsetLeft;
y += el.offsetTop;
while ( el.parentNode )
{
x += el.parentNode.offsetLeft;
y += el.parentNode.offsetTop;
if ( isNaN(el.parentNode.style.borderLeftWidth) )
x += parseInt(el.parentNode.style.borderLeftWidth);
if ( isNaN(el.parentNode.style.borderTopWidth) )
y += parseInt(el.parentNode.style.borderTopWidth);
el = el.parentNode;
if ( typeof el.parentNode.tagName == 'undefined' ) break;
}
return [x, y];
}
var res = getXY(document.getElementById("d0"));
document.getElementById("result").innerHTML = res[0] + ", " + res[1];
</script>
</body>
</html>
Now, if I place the "p" element before the "div" element in the body, simply switching the order, the X and Y coordinates returned for my div will still be "10, 10" but offset top is waaayyy larger than offset left so it just can't be "10, 10" but more like "10, 30" or something to that effect.
This is all because the "p" element has no absolute position defined so by default it's inherited or relative.
What I would like to see is a "10,30" or "10,20" or similar where the Y is larger than X.
I hope this makes sense in what I'm trying to achieve.
Thanks so much for looking into this and I will try the code that 'astupidname' provided me to see if it helps.
I tried your code but received the same values as the function I posted earlier.
I'm really not sure how to solve this problem because what the eye sees on the screen is not 10, 10. It's more like 10, 30 or 10,40 coordinates but for some reason offsetLeft or offsetParent keep returning 10,10.
I thought about adding "*{position:inherit;}" to my css which solves my problem but messes with the stylesheet.
Still looking around for a solution...
if (isNaN(_el.parentNode.style.borderLeftWidth))
x+=parseInt(_el.parentNode.style.borderLeftWidth);
if (isNaN(_el.parentNode.style.borderTopWidth))
y+=parseInt(_el.parentNode.style.borderTopWidth);