Skip to content

Instantly share code, notes, and snippets.

@perry-mitchell
Created December 8, 2017 08:59
Show Gist options
  • Save perry-mitchell/2b29018b07f73e431df5d454bdd9b9e2 to your computer and use it in GitHub Desktop.
Save perry-mitchell/2b29018b07f73e431df5d454bdd9b9e2 to your computer and use it in GitHub Desktop.
True element offset (from document) calculation with debouncing/memoization
import mem from "mem";
const ELEMENT_STYLE_CACHE_TIME = 3000;
let __memoizedGetElementStyle;
export function getElementOffset(target) {
__memoizedGetElementStyle = __memoizedGetElementStyle || mem(getElementStyle, { maxAge: ELEMENT_STYLE_CACHE_TIME });
const boundingRect = target.getBoundingClientRect();
const bodyStyle = __memoizedGetElementStyle(document.body);
let x = parseInt(bodyStyle.marginLeft || 0, 10),
y = parseInt(bodyStyle.marginTop || 0, 10),
el = target;
while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
const elStyle = __memoizedGetElementStyle(el);
const isFixed = /fixed/.test(elStyle.position);
x += el.offsetLeft; // - el.scrollLeft;
y += el.offsetTop; // - el.scrollTop;
if (isFixed) {
x += document.body.scrollLeft;
y += document.body.scrollTop;
break;
}
el = el.offsetParent;
}
return {
top: y,
left: x,
width: boundingRect.width,
height: boundingRect.height
};
}
function getElementStyle(element) {
return window.getComputedStyle(element);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment