getBoundingClientRect needs a bit more care to avoid bugs in scrollY/pageYOffset:
function absolutePosition(el) {
    var
        found,
        left = 0,
        top = 0,
        width = 0,
        height = 0,
        offsetBase = absolutePosition.offsetBase;
    if (!offsetBase && document.body) {
        offsetBase = absolutePosition.offsetBase = document.createElement('div');
        offsetBase.style.cssText = 'position:absolute;left:0;top:0';
        document.body.appendChild(offsetBase);
    }
    if (el && el.ownerDocument === document && 'getBoundingClientRect' in el && offsetBase) {
        var boundingRect = el.getBoundingClientRect();
        var baseRect = offsetBase.getBoundingClientRect();
        found = true;
        left = boundingRect.left - baseRect.left;
        top = boundingRect.top - baseRect.top;
        width = boundingRect.right - boundingRect.left;
        height = boundingRect.bottom - boundingRect.top;
    }
    return {
        found: found,
        left: left,
        top: top,
        width: width,
        height: height,
        right: left + width,
        bottom: top + height
    };
}
The bugs to avoid are:
- scrolling in Android Chrome since Chrome Mobile 43 has wrong values for scrollY/pageYOffset (especially when the keyboard is showing and you scroll). 
- Pinch-zoom in Microsoft IE or Edge causes wrong values for scrollY/pageYOffset. 
- Some (obsolete) browsers don't have a height/width e.g. IE8 
Edit: The above code can be simplified a lot by just using document.body.getBoundingClientRect() instead of adding a div - I haven't tried it though so I am leaving my answer as it stands. Also the body needs margin:0 (reset.css usually does this). This answer simplifies the code down a lot, while still avoiding the bugs in jQuery.offset()!
Edit 2: Chrome 61 introduced window.visualViewport to give correct values for the actual viewport which is probably another way to fix issues; but beware that Android Chrome 66 was still buggy if Settings -> Accessability -> Force enable zoom was ticked (bugs with orientation change, focused inputs, absolutely positioned popup wider than viewport).