Get an Element's Position Using JavaScript

by kirupa | 18 December 2012

While this may be hard to believe, especially if you are familiar with how layout in HTML works, elements are positioned in some sort of sensible manner. Those manners are many and often confusing to discuss here, but there is some logic behind the position of everything you see. With great certainty, all elements end up at a particular location.


This is a companion discussion topic for the original entry at http://www.kirupa.com/html5/get_element_position_using_javascript.htm

Great post. Do you have any copyright policy for the use of this code?

Not at all - do whatever you want with the code snippets and samples :stuck_out_tongue:

Iā€™m only restrictive about the tutorial text & images not being reproduced on other places.

Where do you find the time to write all these great tutorials?? Speaking for myself after spending a full day at work in front of a computer I find it hard to get back on the computer when I get home again. :smile:

I actually find writing and recording videos to be very relaxing :stuck_out_tongue:

Hi. Newbie here, but Iā€™m hoping you can help. I d/l your JS function to find the x,y position of an element on the window. But Iā€™m getting ā€˜undefinedā€™ when I do an alert. However, the element Iā€™m trying to locate is an SVG element in an SVG block. Is that a problem, and if so, how can work around it? Many thanks, and really great work here.

Iā€™m using the getPosition code in an application of mine, and Iā€™m happy with it ā€¦ except for a special case. I have a page containing a DIV with fixed size and overflow=auto, i.e. it creates a scrollbar (vertical in my case) when there is a lot of data. When I move the scrollbar down and want to know the position of an element in this DIV, relative to the browser window, I get wrong results. I found that the reason is that offsetParent skips the DIV with the scrollbar.
I have created a modified version of it which produces the results I want. Here it is:


function getPosYScrolled(ele)
{
  var yPos = 0;

  var eleOffsetParent  = ele;
  var eleParentElement = ele;

   while (eleOffsetParent && eleParentElement)
   {
     if (eleParentElement.tagName == "BODY") // deal with browser quirks with body/window/document and page scroll
     {
       var yScroll = eleOffsetParent.scrollTop || document.documentElement.scrollTop;
       yPos += (eleOffsetParent.offsetTop - yScroll + eleOffsetParent.clientTop);
       eleOffsetParent  = eleOffsetParent.offsetParent;
    }
    else  // for all other non-BODY elements
    { if (eleOffsetParent.isSameNode(eleParentElement))
      {
        yPos += (eleOffsetParent.offsetTop - eleOffsetParent.scrollTop + eleOffsetParent.clientTop);
        eleOffsetParent  = eleOffsetParent.offsetParent;
      }
      else
      {
        if (eleParentElement.tagName == "DIV")
        { yPos -= eleParentElement.scrollTop;  // seems to be a DIV with scrollbar
        }
      }
    }

    eleParentElement = eleParentElement.parentElement;
  }
  return yPos;
}

1 Like

Cool! Thanks for sharing :slight_smile:

getBoundingClientRect and getClientRects have been my standbys in this domain for a long time.

The plural version is useful for overlaying rectangles on top of elements with complex bounding regions like span elements.

Would you care to comment on the following alternative approach for getting an elementā€™s position:
function getPosition(el) {
let rect,X=0,Y=0;
if (el) {
rect=el.getBoundingClientRect();
X = rect.left + window.scrollX;
Y = rect.top + window.scrollY;
}
return { x: X, y: Y }
}
The boundingClientRect() routine gives the elements position relative to the viewport, which in this case is the browser window, and is available in all modern day browsers. It is much simpler than your solution and gives the same results.

That totally works. My reason for not using that API is performance. The getBoundingClientRect API tends to cause unnecessary reflows and style invalidation each time it is called :slight_smile:

That is nice to know and reason to avoid using it, especially on a large page. However, how is one to know that ā€œunnecessary reflowsā€ will occur with this or any other API?

1 Like

If you will be calling the API just once or not as part of a user interaction, that is ok. The way you can find out is by using the browser developer tools. There are only a handful of APIs that fall under this bucket - the other big one being getComputedStyle.

Again thank you. Iā€™ll check the Developer Tools again to look for this. I havenā€™t noticed it before although Iā€™m a very frequent user of the developer tools in all of the browsers that I work with.

1 Like

I am finding a difference in positioning using your code and the one based on the getBoundingClientRect() method. Iā€™ve summarized what I am finding in the following article (http://www.boughner.us/kirupa/element_position.html). I have not been able to determine what is causing this difference so any help that I can get would be appreciated.

A post was split to a new topic: Intellisense