Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get real offset left/top of element with inline offsetparent

I'm trying to get the coordinates of an element on a page. I've been using the standard way to obtain it:

var el = element, pos = {x: 0, y: 0};
while ( el ) {
    pos.x += el.offsetLeft;
    pos.y += el.offsetTop;
    el = el.offsetParent;
}

But this method fails when the element in question has display: block, and one of the offsetParents has display: inline;. This is due to the fact described in this thread:

The element starts in the middle of the text

After some trying with jQuery it turns out that their .offset()-method returns the correct offset, and I've looked through the source but not found exactly how they do it. So my question is: how do I get the exact position? I can't use jQuery for this project, and the method in the thread described earlier is to cumbersome, adding an element and testing is too much work (performance perspective), and using Element.getBoundingClientRect is not available either.

If you feel like trying it out you can go to Apple.com open your debugger of choice and type in the following:

var el, el2;
el = el2 = document.querySelector('#worldwide span');
var pos = {x: 0, y: 0};
while ( el2 ) {
    pos.x += el2.offsetLeft;
    pos.y += el2.offsetTop;
    el2 = el2.offsetParent;
}
alert("Calculated position: " + pos.x + "x" + pos.y + " window size: " + screen.width + "x" + screen.height);

With this code I get: Calculated position: 1354x988 window size: 1280x800 (ie. the offset left is way of the screen, which it clearly isn't)

How is this possible? Any work-around ideas? Approximations? It does not have to be exact, but it has to be better than before. Thanks.

Edit: This is for the WebKit rendering engine, to clarify.

like image 391
Erik Rothoff Avatar asked Mar 28 '11 13:03

Erik Rothoff


People also ask

How do you find the top element of a Offset?

The offsetTop property returns the top position (in pixels) relative to the parent. The returned value includes: the top position, and margin of the element. the top padding, scrollbar and border of the parent.

How do you find the position of an element relative to a parent?

In order to get the location of an element relative to the document, jQuery offset() method is used. The offset() method is an inbuilt method in jQuery which is used to set or returns the offset coordinates of the selected element.

What is the offset parent?

The offset parent is the nearest ancestor that has a position other than static. If no offset parent exists, the offset parent is the document body.


2 Answers

I ended up going with WebKit's window.webkitConvertPointFromNodeToPage, but I kept hitting a bug where it would return a position that was totally wrong. Further investigation revealed that if the node in question was display: inline, then it would return the position of the last block element in the hierarchy.

Searching for a resolution for this image turned up nothing (all I found was very basic information on what webkitConvertPointFromNodeToPage actually did and WebKit's sourcecode).

By guessing I found out that it returned the correct position if the element had display: inline-block, so if the element was inline then I changed it to inline-block and then calculated the position.

If anyone has a better solution for this problem I would love to hear from you!

Edit:

Turns out changing display style to inline-block is not always a good idea, so instead of doing that I'm using this method:

var offset = {x: 0, y: 0};
if ( getStyle(el, 'display') == 'inline' ) {
    offset.x = el.offsetLeft - el.parentNode.offsetLeft;
    offset.y = el.offsetTop - el.parentNode.offsetTop;
}

var point = window.webkitConvertPointFromNodeToPage(el, new WebKitPoint(0, 0));

return {
    x: Math.round(point.x + offset.x),
    y: Math.round(point.y + offset.y)
}

I'm taking the inline child's offsetTop/Left and subtracting that from it's parent. I'm not really sure how it works on parents that have display: inline, but it works 90% of the time.

But if anyone has a better idea I'm still open for suggestions.

like image 129
Erik Rothoff Avatar answered Oct 18 '22 08:10

Erik Rothoff


Probably here you will find the description of the ideas used in the source code of jQuery.offset.

If you look here you can see that offsetLeft and offsetTop works not quite correct in the old IE versions.

I understand that it's interesting to understand how this or other things can be implemented. How you see the source code of jQuery.offset function is not so easy. If you want that your code works correct and be browser independent you should better just use jQuery.offset instead of writing his own implementation it.

like image 22
Oleg Avatar answered Oct 18 '22 09:10

Oleg