i had been using these 7 lines of code which works in all browsers with discrepancies in ie5,6,7(i did not remember having any proboem... may be the doc type) ... quirksmode.org/js/findpos.html and i had been using it a lot for so many years. may be sombody can point the flaws if any. – Jayapal Chandran Apr 2 '15 at 15:27
@AnthonyWJones, I suppose you needed the pedantic pleasure, but it is obvious, as it always is when unspecified, that the OP refers to the most general case, or refers to the window coordinates of the browser. – Motes May 26 '15 at 20:29
@Mote, No, it's not that obvious. Leave inference, subjectivity and false axioms aside. It can be relative to viewport or top of the page (aka document.documentElement). – Andre Figueiredo Oct 22 '17 at 2:27
Defaulting to the most general is not inference, it is the logical progression, so that would be relative to the window, or "top of page" might be the term as you put it. In Game Theory, it is codified as a concept called a Schelling point. Be sure to specify when you don't mean the most general case. – Motes Oct 22 '17 at 18:45
Internet Explorer has supported this since as long as you are likely to care about and it was finally standardized in CSSOM Views. All other browsers adopted it a long time ago.
Some browsers also return height and width properties, though this is non-standard. If you're worried about older browser compatibility, check this answer's revisions for an optimised degrading implementation.
A very interesting article on JS coordinates. This article is mentioned nowhere on SO, it should.. – Ring Ø Feb 19 '14 at 10:55
Doesn't work...it's 8 pixels out vertically and horizontally, due to the 8px margin in the body. Meouw's solution works perfectly. If you want I have a small test to demonstrate the problem. – CpnCrunch Jul 1 '14 at 2:30
Actually, I think it depends what you actually want to get the coords of. The question is a little ambiguous. Your answer is correct if you just want the coords relative to the viewport or relative to the body element, but that doesn't help you in the case where you want the absolute position of the element (which I imagine is what most people want). meouw's answer doesn't give you that either, unless you remove the '-scrollLeft' and '-scrollTop' bits. – CpnCrunch Jul 3 '14 at 17:58
@CpnCrunch: I see what you mean now; I didn't realise you were referring to the latter part of my answer. When the body has a margin, its bounding box will be offset by that number of pixels at each respective side. In that case, you'd also have to subtract the computed margin style from the body coordinates. It's worth noting that CSS resets remove the margin from <body>, though. – Andy E Jul 4 '14 at 15:14
This answers solution elemRect.top - bodyRect.top and similarly elemRect.left - bodyRect.left is fortunately zoom-tolerant. jQuery's offset() gives different results when the window is zoomed in Android Chrome. jQuery surrenders regarding offset(): dimensions may be incorrect when the page is zoomed by the user; browsers do not expose an API to detect this condition. Using this answers solution you don't need an API to detect zoom condition. – Timo Kähkönen May 31 '15 at 17:12
change: el = el.parentNode to: el = el.offsetParent; and it seems to work for nested iframes now... I'm thinking that's what you intended? – Adam Jul 29 '09 at 20:19
This solution is incomplete. Try putting a thick border on a div and nest it a few times. In any version of Firefox (2-5) it will be off by the border width(s) (even in standards compliance mode). – ck_ Aug 5 '11 at 5:21
isn't there a cleaner way to do that, like a el.totalOffsetLeft and totalOffsetTop function? jQuery certainly has this option but it's a shame there is no official method for this, do we need to wait DOM4? I'm building an HTML5 canvas application, so I think the best solution would be to insert canvas element in an iframe so I can get real coordinates with clientX and clientY when we click on element. – baptx May 30 '12 at 17:04
So, @Adam and meouw, are you saying the first code block is wrong? Then why not remove that altogether? (This question has seen quite some viewers over the years; might be nice to remove things if they are wrong?) – Arjan Aug 11 '12 at 23:35
maybe its not a winner cause its the same as Andy E's solution, but doesn't work in old browsers < IE9 – niltoid Jun 10 '16 at 21:36
getBoundingClientRect causes a massive repaint spike in my performance charts – frumbert Nov 22 '17 at 4:14
As a general rule, it's not advisable to reuse variables, but here it's really weird to reuse el, why not var rect = ... or something? it's much more clear. – tokland Jun 25 at 8:41
If page includes - at least- any "DIV", the function given by meouw throws the "Y" value beyond current page limits. In order to find the exact position, you need to handle both offsetParent's and parentNode's.
as with the other solutions even with FF 24.4 the above code does not work when border widths exist as part of the positioning layout. – rob May 12 '14 at 20:46
You're a life saver. I'm working through some pretty deep GWT bugs right now and throwing this in a JSNI method solves all my problems!! – Will Byrne Jun 10 '15 at 21:27
modifying Element.prototype is generally considered a bad idea. It leads to really hard to maintain code. Also, this code doesn't account for scrolling. – Jared Forsyth Jun 22 '15 at 21:58
These specifiy the position of the element relative its nearest parent that has layout. This parent can often be accessed bif the offsetParent property.
These properties are less common, they specify an elements position with its parents client area (padded area is part of the client area but border and margin is not).
To retrieve the position relative to the page efficiently, and without using a recursive function: (includes IE also)
Including the all important scrollTop/scrollLeft makes this answer a bit more correct. – scunliffe Dec 6 '14 at 22:24
How about something like this, by passing ID of the element and it will return the left or top, we can also combine them:
You might be better served by using a JavaScript framework, that has functions to return such information (and so much more!) in a browser-independant fashion. Here are a few:
With these frameworks, you could do something like: $('id-of-img').top to get the y-pixel coordinate of the image.
@Costa They all use those sorts of functions, although this is an evolving field, as different browsers conform differently to the specification. So much of the code deals with "fixing" things that go wrong. You really should look at the source code. – Shalom Craimer Mar 27 '13 at 17:38
@scraimer: jQuery and YUI are NOT frameworks!!! These are libraries! It's not the same. Citing jquery.com: "jQuery is a fast, small, and feature-rich JavaScript library." Citing yuilibrary.com (you can see the "magic" word in the URL too...): "YUI is a free, open source JavaScript and CSS library for building richly interactive web applications." – Sk8erPeter May 9 '13 at 11:34
So you should use huge libraries just for this simple task? Not necessary. I hate that every time I want to do something with js, I get these jQuery solutions. jQuery is not JS! – Opptatt Jobber Oct 11 '13 at 19:14
@OpptattJobber I agree...JQuery is not javascript. It relies on Javascript but its a different programming language altogether. – Nick Manning Mar 27 '14 at 0:31
@NickManning Its not a new language, its an abstraction layer for the DOM that eliminates having to write compatibility and performance workarounds directly into your code. If you don't use jQuery, you should be using some type of abstraction layer anyways. – ginman Apr 4 '14 at 15:01
For some reason it is not giving the same results in IE compared to other browsers. I think that in IE it is giving position relative to the window, so if you scroll, you will be getting different results in IE compared to others – Abdul Rahim Haddad Aug 10 '13 at 16:19
offset() is confused by zoom, at least in Android Chrome, so it is useless. stackoverflow.com/a/11396681/1691517 shows zoom-tolerant way. – Timo Kähkönen May 31 '15 at 18:45
I've taken @meouw's answer, added in the clientLeft that allows for the border, and then created three versions:
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.
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.
Interesting ... but on Edge getAbsoluteOffsetFromBody(element).top returns a different value as I scroll, in Chrome it stays consistent as I scroll. It seems Edge is adjusting with scroll position. When the element is scrolled out of view I get a negative value. – Norman Jan 13 at 16:13
getAbsoluteOffsetFromRelative made my day, i had to reproduce bootstrap tooltip without Javascript of bootstrap, it helped me a lot. – Nolyurn Aug 13 at 15:52
Plus the bonus of using jQuery is it's lightweight file size and easy use, you won't go back to JavaScript without it afterwards.
This is the best code I've managed to create (works in iframes as well, unlike jQuery's offset()). Seems webkit has a bit of a different behavior.
Note that you'll need jQuery to use $.browser.webkit; You'll need to play around with navigator.userAgent to do the same with pure JavaScript. – Sathvik Mar 7 '12 at 2:47
unfortunately even with FF 24.4 the above code does not work when border widths exist as part of the positioning layout. – rob May 12 '14 at 20:43
The cleanest approach I have found is a simplified version of the technique used by jQuery's offset. Similar to some of the other answers it starts with getBoundingClientRect; it then uses the window and the documentElement to adjust for scroll position as well as things like the margin on the body (often the default).
While this is very likely to be lost at the bottom of so many answers, the top solutions here were not working for me.
In an HTML5 page I had a menu that was a nav element inside a header (not THE header but a header in another element).
I wanted the navigation to stick to the top once a user scrolled to it, but previous to this the header was absolute positioned (so I could have it overlay something else slightly).
The solutions above never triggered a change because .offsetTop was not going to change as this was an absolute positioned element. Additionally the .scrollTop property was simply the top of the top most element... that is to say 0 and always would be 0.
Any tests I performed utilizing these two (and same with getBoundingClientRect results) would not tell me if the top of the navigation bar ever scrolled to the top of the viewable page (again, as reported in console, they simply stayed the same numbers while scrolling occurred).
The value of the pageTop property reflects the viewable section of the screen, therefore allowing me to track where an element is in reference to the boundaries of the viewable area.
Probably unnecessary to say, anytime I am dealing with scrolling I expect to use this solution to programatically respond to movement of elements being scrolled.
IMPORTANT NOTE: This appears to work in Chrome and Opera currently & definitely not in Firefox (6-2018)... until Firefox supports visualViewport I recommend NOT using this method, (and I hope they do soon... it makes a lot more sense than the rest).
While I still find what I discovered to be very valuable for situations in which "...programmatically respond to movement of elements being scrolled." is applicable. The better solution for the problem that I had was to use CSS to set position: sticky on the element. Using sticky you can have an element stay at the top without using javascript (NOTE: there are times this will not work as effectively as changing the element to fixed but for most uses the sticky approach will likely be superior)
So I realized that for a different page I had a requirement where I needed to detect the position of an element in a mildly complex scrolling setup (parallax plus elements that scroll past as part of a message). I realized in that scenario that the following provided the value I utilized to determine when to do something:
this is very likely to be at the top of so many answers when you click active to sort the answers – lucchi Jun 1 at 11:48
@lucchi :D well I suppose I could remove the text @ the top... though I just happened on this one again and realized that I'd found a better solution for my own problem... though my answer is more of a foot note to the more complete answers. I suspect my requirements were maybe not that common that the other answers didn't work for me? – MER Jun 1 at 20:14
I appreciate your answer anyway, it was just to tell you that, anybody willing will be aware that you wrote something new. You are not alone.... – lucchi Jun 1 at 22:22
I successfully used Andy E's solution to position a bootstrap 2 modal depending on what link in a table row a user clicks on. The page is a Tapestry 5 page and javascript below is imported in the java page class.
This js code helped me, I have an old webforms app using multiple placeholders inject .aspx pages and I could not figure out how to appendChild() of a popup box I was creating to get it into the viewport because the entire DOM tree is whack with the multiple placeholders and incorrect markup. Using the body.getBoundingClientRect() then using its top in positioning was what I needed. Thanks. – Brad Martin Aug 14 '15 at 21:32
Since different browsers are rendering border, padding, margin and etc in different way. I wrote a little function to retrieve top and left positions of specific element in every root element that you want in precise dimension:
@MacroMan, I respects your decision but I have already explained in the text that the "bottom and right the code is not tested.". Also, i will update my code very soon. – Vishal May 8 at 16:56
I think it's el.offsetTop and el.offsetLeft (the OP doesn't say anything about jQuery... I'm not sure why your answer uses jQuery either...) – mesqueeb Jul 10 at 6:57