Skip to content

Instantly share code, notes, and snippets.

@rgrove
Created April 25, 2013 21:20
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rgrove/5463265 to your computer and use it in GitHub Desktop.
Save rgrove/5463265 to your computer and use it in GitHub Desktop.
Simple JS function that returns a bounding rect for an element with absolute coordinates corrected for scroll positions.
/**
Returns a bounding rect for _el_ with absolute coordinates corrected for
scroll positions.
The native `getBoundingClientRect()` returns coordinates for an element's
visual position relative to the top left of the viewport, so if the element
is part of a scrollable region that has been scrolled, its coordinates will
be different than if the region hadn't been scrolled.
This method corrects for scroll offsets all the way up the node tree, so the
returned bounding rect will represent an absolute position on a virtual
canvas, regardless of scrolling.
@method getAbsoluteBoundingRect
@param {HTMLElement} el HTML element.
@return {Object} Absolute bounding rect for _el_.
**/
function getAbsoluteBoundingRect (el) {
var doc = document,
win = window,
body = doc.body,
// pageXOffset and pageYOffset work everywhere except IE <9.
offsetX = win.pageXOffset !== undefined ? win.pageXOffset :
(doc.documentElement || body.parentNode || body).scrollLeft,
offsetY = win.pageYOffset !== undefined ? win.pageYOffset :
(doc.documentElement || body.parentNode || body).scrollTop,
rect = el.getBoundingClientRect();
if (el !== body) {
var parent = el.parentNode;
// The element's rect will be affected by the scroll positions of
// *all* of its scrollable parents, not just the window, so we have
// to walk up the tree and collect every scroll offset. Good times.
while (parent !== body) {
offsetX += parent.scrollLeft;
offsetY += parent.scrollTop;
parent = parent.parentNode;
}
}
return {
bottom: rect.bottom + offsetY,
height: rect.height,
left : rect.left + offsetX,
right : rect.right + offsetX,
top : rect.top + offsetY,
width : rect.width
};
}
@tpaksu
Copy link

tpaksu commented Nov 14, 2017

I would change
while (parent !== body) {

to

while(parent !== body && parent !== null) {

to prevent null object exceptions.

@matthew-dean
Copy link

matthew-dean commented Jul 9, 2018

Just a warning for others who might happen upon this gist. The only thing about this (I've now discovered) is that the "absolute position" can't really reliably tell you where components are in relation to each other. Specifically with position fixed / absolute. Those will have an absolute rect position that will seem to be "above" other content until after scroll.

So if you naively assume you can get "absolute coordinates" of all elements on the page, you really can't. You have to measure after scroll changes anyway. :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment