85

I want to know how to use JavaScript to get the distance of an element from the top of the page not the parent element.
enter image description here

http://jsfiddle.net/yZGSt/1/

Sami Al-Subhi
  • 2,984
  • 6
  • 27
  • 45
  • 2
    possible duplicate of [Determine distance from the top of a div to top of window with javascript](http://stackoverflow.com/questions/9880472/determine-distance-from-the-top-of-a-div-to-top-of-window-with-javascript) – T.Todua Sep 23 '15 at 11:26

13 Answers13

100

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.

crg
  • 2,088
  • 1
  • 8
  • 27
Shawn Whinnery
  • 3,069
  • 3
  • 13
  • 16
  • 2
    element in this case would be something like: `var element = document.querySelectorAll('.wrapper')[0];` – Colton45 Sep 14 '17 at 00:34
  • insanely useful! – Rok Sprogar Oct 07 '17 at 19:13
  • 1
    @Colton45 actually you should use `document.querySelector('.wrapper')` – Guilherme Nagatomo Dec 21 '17 at 15:59
  • 2
    Just to further add to this, this implementation does not function the same in Safari as Chrome - therefore I would argue it should not be accepted. Here is a demo (scroll on both browsers): https://codepen.io/anon/pen/LaKEPK. This implementation https://stackoverflow.com/a/53351648/775007 works. – Dean Mar 27 '19 at 13:46
  • @Dean You sure about that? It's working for me in every brower and OS I have available. I think you might have confused yourself by using vh units in your css lol. https://codepen.io/anon/pen/zXqqbP – Shawn Whinnery Apr 04 '19 at 17:48
  • @ShawnWhinnery Yes i'm sure. I just tried your codepen and the behaviour is the same. The value changes as you scroll in one browser and doesn't in the other :) – Dean Apr 05 '19 at 19:15
70
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).

eeglbalazs
  • 1,108
  • 9
  • 10
13

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>
www139
  • 4,141
  • 2
  • 25
  • 53
9

Use offsetTop

document.getElementById("foo").offsetTop

Demo

Buts
  • 2,063
  • 1
  • 25
  • 41
sachleen
  • 28,887
  • 7
  • 71
  • 71
6

offsetTop doesn’t get the distance to the top of the page, but rather to the top of the closest parent element that has a specified position.

You can use a simple technique that adds up the offsetTop of all the parent element of the element you are interested in to get the distance.

// Our element
var elem = document.querySelector('#some-element');

// Set our distance placeholder
var distance = 0;

// Loop up the dom
do {
    // Increase our distance counter
    distance += elem.offsetTop;

    // Set the element to it's parent
    elem = elem.offsetParent;

} while (elem);
distance = distance < 0 ? 0 : distance;

Original code from https://gomakethings.com/how-to-get-an-elements-distance-from-the-top-of-the-page-with-vanilla-javascript/

  • 13
    It's surreal to Google how to do something and discover a StackOverflow answer that links back an article YOU wrote. LOL thanks for this! – Chris Ferdinandi Mar 12 '19 at 14:59
4
var distanceTop = element.getBoundingClientRect().top;

For details vist a link:

https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect

Shree
  • 18,997
  • 28
  • 86
  • 133
Kelvin Jardin
  • 81
  • 1
  • 1
  • 1
    A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](//stackoverflow.com/help/deleted-answers) – Filnor Mar 16 '18 at 09:41
  • 6
    This will not give actual height from top. It returns the height from top at current scrolled state of the window. – blackspacer Jan 22 '19 at 13:03
2

Although it is quite an old discussion, but this works pretty well on chrome / firefox / safari browsers:

window.addEventListener('scroll', function() {
   var someDiv = document.getElementById('someDiv');
   var distanceToTop = someDiv.getBoundingClientRect().top;
});

Check it out on JSFiddle

CodeMonk
  • 920
  • 1
  • 12
  • 21
2

scroll to element's top position;

var rect = element.getBoundingClientRect();
var offsetTop = window.pageYOffset + rect.top - rect.height;
Aras Ksgl
  • 21
  • 2
1

(SOURCE : Determine distance from the top of a div to top of window with javascript )

<script type="text/javascript">
var myyElement = document.getElementById("myyy_bar");  //your element
var EnableConsoleLOGS = true;                          //to check the results in Browser's Inspector(Console), whenever you are scrolling



// ==============================================
window.addEventListener('scroll', function (evt) {
    var Positionsss =  GetTopLeft ();  
    if (EnableConsoleLOGS) { console.log(Positionsss); }
});
function GetOffset (object, offset) {
    if (!object) return;
    offset.x += object.offsetLeft;       offset.y += object.offsetTop;
    GetOffset (object.offsetParent, offset);
}
function GetScrolled (object, scrolled) {
    if (!object) return;
    scrolled.x += object.scrollLeft;    scrolled.y += object.scrollTop;
    if (object.tagName.toLowerCase () != "html") {          GetScrolled (object.parentNode, scrolled);        }
}

function GetTopLeft () {
    var offset = {x : 0, y : 0};        GetOffset (myyElement, offset);
    var scrolled = {x : 0, y : 0};      GetScrolled (myyElement.parentNode, scrolled);
    var posX = offset.x - scrolled.x;   var posY = offset.y - scrolled.y;
    return {lefttt: posX , toppp: posY };
}
// ==============================================
</script>
Community
  • 1
  • 1
T.Todua
  • 44,747
  • 17
  • 195
  • 185
1

warning warning warning warning warning warning

"Classic case" - URL "/#about-us" and div with an id of "about-us". In this case, the top position set by default anchor click behavior (So the top is 0 for about-us div). You must prevent default (Or you'll go crazy for why it doesn't work -or- any other code you find out there). More details below under "warning".

1

Less than 30 seconds solution (Two lines of code "hello world"):

get your element:

var element = document.getElementById("hello");

Get getBoundingClientRect ();

The Element.getBoundingClientRect() method returns the size of an element and its position relative to the viewport. https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect

var rect = element.getBoundingClientRect();

Return object:

enter image description here

Dot notation top

var distance_from_top = rect.top; /* 1007.9971313476562 */

Thats it.

2

StackOverflow nightmare 2 - set scroll position to this value

Again "hello world" (8,000 answers out there - 7,999 not working or to complex).

https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo

  window.scrollTo({
    top: element.getBoundingClientRect().top,
    behavior: 'smooth'
  });

Add offset value to top if you want (For sticky navbars).

"Hello World" code snippet (Get distance from top viewport + click to scrollTo)

var element = document.getElementById("hello");
var rect = element.getBoundingClientRect();
var distance_from_top = rect.top; /* 50px */
console.log(distance_from_top);

function scrollTovView(){
  window.scrollTo({
    top: distance_from_top,
    behavior: 'smooth'
  });
}
div{
  text-align:center;
  border: 1px solid lightgray;
}
<button onclick="scrollTovView()">scrollTo to red DIV</button>
<div style="height: 50px;">50px height</div>
<div id="hello" style="width: 500px; height: 500px; background: red;"></div>

warning

scrollTo "conflict" with main anchor navbars

This trick is very buggy if, for example, you use this URL (ID to anchor URL)(Top is 0 or "get crazy" hh).

www.mysite/about#hello
  window.scrollTo({
    top: element.getBoundingClientRect().top,
    behavior: 'smooth'
  });

For this code to work you should add:

    if (this.hash !== "") {
      // Prevent default anchor click behavior
      event.preventDefault();

Basic example her: https://www.w3schools.com/howto/howto_css_smooth_scroll.asp

Ezra Siton
  • 3,516
  • 2
  • 10
  • 16
0

This function returns distance from top of the page, even if your window is scrolled. It can be used in event listeners.

const getElementYOffset = (element) => {
  const scrollOnWindow =
    window.pageYOffset !== undefined
      ? window.pageYOffset
      : (document.documentElement || document.body.parentNode || document.body)
          .scrollTop;
  const rect = element.getBoundingClientRect();
  let distanceFromTopOfPage = rect.top;
  if (scrollOnWindow !== 0) {
    distanceFromTopOfPage = rect.top + scrollOnWindow;
  }

  return distanceFromTopOfPage;
};
David Buck
  • 3,439
  • 29
  • 24
  • 31
Uzma Ali
  • 1
  • 1
0

This oneliner seems to work nice

document.getElementById("el").getBoundingClientRect().top +  window.scrollY

your fiddle updated

Fanky
  • 1,152
  • 12
  • 18
-7

Using jQuery's offset() method:

$(element).offset().top

Example: http://jsfiddle.net/yZGSt/3/

Alan Haggai Alavi
  • 67,398
  • 19
  • 96
  • 124