How to get an element's top position relative to the browser's viewport?

Javascript

Javascript Problem Overview


I want to get the position of an element relative to the browser's viewport (the viewport in which the page is displayed, not the whole page). How can this be done in JavaScript?

Many thanks

Javascript Solutions


Solution 1 - Javascript

The existing answers are now outdated. The native getBoundingClientRect() method has been around for quite a while now, and does exactly what the question asks for. Plus it is supported across all browsers (including IE 5, it seems!)

From MDN page:

The returned value is a TextRectangle object, which contains read-only left, top, right and bottom properties describing the border-box, in pixels, with the top-left relative to the top-left of the viewport.

You use it like so:

var viewportOffset = el.getBoundingClientRect();
// these are relative to the viewport, i.e. the window
var top = viewportOffset.top;
var left = viewportOffset.left;

Solution 2 - Javascript

On my case, just to be safe regarding scrolling, I added the window.scroll to the equation:

var element = document.getElementById('myElement');
var topPos = element.getBoundingClientRect().top + window.scrollY;
var leftPos = element.getBoundingClientRect().left + window.scrollX;

That allows me to get the real relative position of element on document, even if it has been scrolled.

Solution 3 - Javascript

var element =  document.querySelector('selector');
var bodyRect = document.body.getBoundingClientRect(),
    elemRect = element.getBoundingClientRect(),
    offset   = elemRect.top - bodyRect.top;

Solution 4 - Javascript

Edit: Add some code to account for the page scrolling.

function findPos(id) {
    var node = document.getElementById(id);		
    var curtop = 0;
    var curtopscroll = 0;
    if (node.offsetParent) {
        do {
            curtop += node.offsetTop;
            curtopscroll += node.offsetParent ? node.offsetParent.scrollTop : 0;
        } while (node = node.offsetParent);

        alert(curtop - curtopscroll);
    }
}

The id argument is the id of the element whose offset you want. Adapted from a quirksmode post.

Solution 5 - Javascript

jQuery implements this quite elegantly. If you look at the source for jQuery's offset, you'll find this is basically how it's implemented:

var rect = elem.getBoundingClientRect();
var win = elem.ownerDocument.defaultView;

return {
	top: rect.top + win.pageYOffset,
	left: rect.left + win.pageXOffset
};

Solution 6 - Javascript

function inViewport(element) {
    let bounds = element.getBoundingClientRect();
	let viewWidth = document.documentElement.clientWidth;
	let viewHeight = document.documentElement.clientHeight;

    if (bounds['left'] < 0) return false;
    if (bounds['top'] < 0) return false;
	if (bounds['right'] > viewWidth) return false;
	if (bounds['bottom'] > viewHeight) return false;

    return true;
}

source

Solution 7 - Javascript

The function on this page will return a rectangle with the top, left, height and width co ordinates of a passed element relative to the browser view port.

    localToGlobal: function( _el ) {
       var target = _el,
       target_width = target.offsetWidth,
       target_height = target.offsetHeight,
       target_left = target.offsetLeft,
       target_top = target.offsetTop,
       gleft = 0,
       gtop = 0,
       rect = {};
    
       var moonwalk = function( _parent ) {
    	if (!!_parent) {
    		gleft += _parent.offsetLeft;
    		gtop += _parent.offsetTop;
    		moonwalk( _parent.offsetParent );
    	} else {
    		return rect = {
    		top: target.offsetTop + gtop,
    		left: target.offsetLeft + gleft,
    		bottom: (target.offsetTop + gtop) + target_height,
    		right: (target.offsetLeft + gleft) + target_width
    		};
    	}
    };
    	moonwalk( target.offsetParent );
    	return rect;
}

Solution 8 - Javascript

You can try:

node.offsetTop - window.scrollY

It works on Opera with viewport meta tag defined.

Solution 9 - Javascript

Thanks for all the answers. It seems Prototype already has a function that does this (the page() function). By viewing the source code of the function, I found that it first calculates the element offset position relative to the page (i.e. the document top), then subtracts the scrollTop from that. See the source code of prototype for more details.

Solution 10 - Javascript

I am assuming an element having an id of btn1 exists in the web page, and also that jQuery is included. This has worked across all modern browsers of Chrome, FireFox, IE >=9 and Edge. jQuery is only being used to determine the position relative to document.

var screenRelativeTop =  $("#btn1").offset().top - (window.scrollY || 
                                            window.pageYOffset || document.body.scrollTop);

var screenRelativeLeft =  $("#btn1").offset().left - (window.scrollX ||
                                           window.pageXOffset || document.body.scrollLeft);

Solution 11 - Javascript

Sometimes getBoundingClientRect() object's property value shows 0 for IE. In that case you have to set display = 'block' for the element. You can use below code for all browser to get offset.

Extend jQuery functionality :

(function($) {
    jQuery.fn.weOffset = function () {
        var de = document.documentElement;
        $(this).css("display", "block");
        var box = $(this).get(0).getBoundingClientRect();
        var top = box.top + window.pageYOffset - de.clientTop;
        var left = box.left + window.pageXOffset - de.clientLeft;
        return { top: top, left: left };
    };
}(jQuery));

Use :

var elementOffset = $("#" + elementId).weOffset();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWaleed EissaView Question on Stackoverflow
Solution 1 - JavascriptHimanshu PView Answer on Stackoverflow
Solution 2 - JavascriptFabio NolascoView Answer on Stackoverflow
Solution 3 - JavascriptGURU PRASADView Answer on Stackoverflow
Solution 4 - JavascriptDerek SwingleyView Answer on Stackoverflow
Solution 5 - JavascriptjordancoopermanView Answer on Stackoverflow
Solution 6 - JavascriptkarlsebalView Answer on Stackoverflow
Solution 7 - JavascriptrismView Answer on Stackoverflow
Solution 8 - JavascriptSzere DyeriView Answer on Stackoverflow
Solution 9 - JavascriptWaleed EissaView Answer on Stackoverflow
Solution 10 - JavascriptSunilView Answer on Stackoverflow
Solution 11 - JavascriptArifView Answer on Stackoverflow