How to get the distance from the top for an element?

Solution 1:

var elDistanceToTop = window.pageYOffset + el.getBoundingClientRect().top

In my experience document.body.scrollTop doesn't always return the current scroll position (for example if the scrolling actually happens on a different element).

Solution 2:

offsetTop only looks at the element's parent. Just loop through parent nodes until you run out of parents and add up their offsets.

function getPosition(element) {
    var xPosition = 0;
    var yPosition = 0;

    while(element) {
        xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
        yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
        element = element.offsetParent;
    }

    return { x: xPosition, y: yPosition };
}

UPDATE: This answer has some problems, values will have tiny differences compare to what it should be and will not work correctly in some cases.

Check @eeglbalazs's answer, which is accurate.

Solution 3:

Here is some interesting code for you :)

window.addEventListener('load', function() {
  //get the element
  var elem = document.getElementById('test');
  //get the distance scrolled on body (by default can be changed)
  var distanceScrolled = document.body.scrollTop;
  //create viewport offset object
  var elemRect = elem.getBoundingClientRect();
  //get the offset from the element to the viewport
  var elemViewportOffset = elemRect.top;
  //add them together
  var totalOffset = distanceScrolled + elemViewportOffset;
  //log it, (look at the top of this example snippet)
  document.getElementById('log').innerHTML = totalOffset;
});
#test {
  width: 100px;
  height: 100px;
  background: red;
  margin-top: 100vh;
}
#log {
  position: fixed;
  top: 0;
  left: 0;
  display: table;
  background: #333;
  color: #fff;
}
html,
body {
  height: 2000px;
  height: 200vh;
}
<div id="log"></div>
<div id="test"></div>