How can I retrieve the offset of a container relative to a parent with pure JS?
7 Answers
element.offsetLeft
and element.offsetTop
give an element's position with respect to its offsetParent
(which is the nearest parent element with a position of relative
or absolute
.)

- 35,956
- 47
- 141
- 220

- 15,612
- 3
- 40
- 40
-
21Element's positioned `static` are not offset parents. – Esailija Jul 24 '12 at 16:05
-
5don't use semicolons inside braces, use commas – Luca Borrione Jun 21 '13 at 16:28
-
1what about position fixed? are they offset parents? – Ayyash Apr 28 '14 at 05:48
-
1Yes, @Ayya- position fixed also creates a new offset context – mmmeff May 07 '15 at 21:10
-
please correct the answer since Zepto was a short-lived joke and jQuery is still and forever the king. – vsync Jun 06 '17 at 19:51
-
17@vsync jQuery is not the king of anything since ie9 reached EOL in January 2016, we have a standardised DOM selection in all major browsers, learn pure js. Also opinions about what framework to use have no place on SO, since it heavily depends on the project and target platform. – Hans Koch Mar 16 '18 at 07:34
-
Seems it always returns 0 if parent element scrolls? e.g. has `overflow: scroll` or `overflow: auto` ? – Peter Hollingsworth Feb 02 '23 at 18:01
in pure js just use offsetLeft
and offsetTop
properties.
Example fiddle: http://jsfiddle.net/WKZ8P/
var elm = document.querySelector('span');
console.log(elm.offsetLeft, elm.offsetTop);
p { position:relative; left:10px; top:85px; border:1px solid blue; }
span{ position:relative; left:30px; top:35px; border:1px solid red; }
<p>
<span>paragraph</span>
</p>

- 118,978
- 58
- 307
- 400

- 120,726
- 26
- 164
- 177
-
Thank you. Is there also a way to get the offset to a parent.parent element? – matt Jul 24 '12 at 16:09
-
3`p.offsetTop + p.parentNode.offsetTop` You could wrap this in a recursive function call much [like PPK proposed](http://www.quirksmode.org/js/findpos.html) a few years ago. You could alter the function to either pass the number of levels to go up or use a selector to mimic `$(selector).parents(parentSelector)`. I would prefer this solution because the zepto implementation only works on browsers supporting `getBoundingClientsRect` - which some mobiles don't. – Torsten Walter Jul 24 '12 at 21:21
-
I thought `getBoundingClientsRect` was widely supported... if anyone knows which mobiles do not support it I would be interested (can't find any support table for mobiles about it). – Aurelio Jul 01 '14 at 11:54
-
This is probably the most correct answer even though it's not marked. My personal solution was changing `$(this).offset().left` to `this.offsetLeft`. – adjwilli Aug 06 '14 at 15:10
-
This also fixes wrong `jQuery.position()` behavior inside of a 3d transformed parent, thank you so much! – rassoh Dec 03 '17 at 15:05
-
-1 , It works relative to "offsetParent"(https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent) which is NOT always the parent element, so this method won't work if the parent element is not positioned. – aderchox Jul 23 '21 at 14:02
I did it like this in Internet Explorer.
function getWindowRelativeOffset(parentWindow, elem) {
var offset = {
left : 0,
top : 0
};
// relative to the target field's document
offset.left = elem.getBoundingClientRect().left;
offset.top = elem.getBoundingClientRect().top;
// now we will calculate according to the current document, this current
// document might be same as the document of target field or it may be
// parent of the document of the target field
var childWindow = elem.document.frames.window;
while (childWindow != parentWindow) {
offset.left = offset.left + childWindow.frameElement.getBoundingClientRect().left;
offset.top = offset.top + childWindow.frameElement.getBoundingClientRect().top;
childWindow = childWindow.parent;
}
return offset;
};
=================== you can call it like this
getWindowRelativeOffset(top, inputElement);
I focus on IE only as per my focus but similar things can be done for other browsers.

- 897
- 9
- 17

- 139
- 2
- 1
-
It throws error for me on `elem.document.frames` says documents is undefined – Vedmant May 08 '22 at 11:21
Add the offset of the event to the parent element offset to get the absolute offset position of the event.
An example :
HTMLElement.addEventListener('mousedown',function(e){
var offsetX = e.offsetX;
var offsetY = e.offsetY;
if( e.target != this ){ // 'this' is our HTMLElement
offsetX = e.target.offsetLeft + e.offsetX;
offsetY = e.target.offsetTop + e.offsetY;
}
}
When the event target is not the element which the event was registered to, it adds the offset of the parent to the current event offset in order to calculate the "Absolute" offset value.
According to Mozilla Web API: "The HTMLElement.offsetLeft read-only property returns the number of pixels that the upper left corner of the current element is offset to the left within the HTMLElement.offsetParent node."
This mostly happens when you registered an event on a parent which is containing several more children, for example: a button with an inner icon or text span, an li
element with inner spans. etc...

- 10,205
- 6
- 55
- 80
-
What about the parent of the parent? What about nested elements having scrollbars? What about previous elements with display:none? A true document offset position is almost impossible to calculate, yet the rendering engine can know it. Too bad simple properties like document position were never included in DOM. – David Spector Dec 07 '18 at 01:01
-
I got another Solution. Subtract parent property value from child property value
$('child-div').offset().top - $('parent-div').offset().top;

- 5,670
- 2
- 44
- 39
Example
So, if we had a child element with an id of "child-element" and we wanted to get it's left/top position relative to a parent element, say a div that had a class of "item-parent", we'd use this code.
var position = $("#child-element").offsetRelative("div.item-parent");
alert('left: '+position.left+', top: '+position.top);
Plugin Finally, for the actual plugin (with a few notes explaining what's going on):
// offsetRelative (or, if you prefer, positionRelative)
(function($){
$.fn.offsetRelative = function(top){
var $this = $(this);
var $parent = $this.offsetParent();
var offset = $this.position();
if(!top) return offset; // Didn't pass a 'top' element
else if($parent.get(0).tagName == "BODY") return offset; // Reached top of document
else if($(top,$parent).length) return offset; // Parent element contains the 'top' element we want the offset to be relative to
else if($parent[0] == $(top)[0]) return offset; // Reached the 'top' element we want the offset to be relative to
else { // Get parent's relative offset
var parent_offset = $parent.offsetRelative(top);
offset.top += parent_offset.top;
offset.left += parent_offset.left;
return offset;
}
};
$.fn.positionRelative = function(top){
return $(this).offsetRelative(top);
};
}(jQuery));
Note : You can Use this on mouseClick or mouseover Event
$(this).offsetRelative("div.item-parent");

- 897
- 9
- 17

- 5,670
- 2
- 44
- 39
-
1I don't see scrolling accounted for. There are lots of odd cases that can happen. – David Spector Dec 07 '18 at 01:04
-
jquery.min.js:2 Uncaught RangeError: Maximum call stack size exceeded this is the error it throwing – Ujjual Dec 21 '21 at 12:46
-
3
Sure is easy with pure JS, just do this, work for fixed and animated HTML 5 panels too, i made and try this code and it works for any brower (include IE 8):
<script type="text/javascript">
function fGetCSSProperty(s, e) {
try { return s.currentStyle ? s.currentStyle[e] : window.getComputedStyle(s)[e]; }
catch (x) { return null; }
}
function fGetOffSetParent(s) {
var a = s.offsetParent || document.body;
while (a && a.tagName && a != document.body && fGetCSSProperty(a, 'position') == 'static')
a = a.offsetParent;
return a;
}
function GetPosition(s) {
var b = fGetOffSetParent(s);
return { Left: (b.offsetLeft + s.offsetLeft), Top: (b.offsetTop + s.offsetTop) };
}
</script>

- 157
- 1
- 5
-
Did you test with all possible cases of parent nodes and element properties? Does this account for scrolling and nested scrolling? – David Spector Dec 07 '18 at 01:03