Created
April 25, 2013 21:20
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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 | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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. :/