ThinkCode
ThinkCode

Reputation: 145

offsetTop return 0

I'm trying to develop a function which move a div-Element to the same height as the hovered element. For this I used offsetTop but it always returns 0 and I don't get what I'm doing wrong.

$( document ).ready(function() {
            const handle = document.querySelector('#handle');


            const headers = document.querySelectorAll('.et_pb_accordion_item_0, .et_pb_accordion_item_1, .et_pb_accordion_item_2')
                .forEach(el => {
                  el.addEventListener('mouseover', e => {
                      handle.style.top = `${e.currentTarget.offsetTop}px`;
                });
            });
        });

I also tried to use getBoundingClientRect().top but it return different values if I scroll dwon

Upvotes: 10

Views: 19642

Answers (4)

jperl
jperl

Reputation: 5112

The offsetTop property is relative to the top padding edge of the offsetParent, whereas getBoundingClientRect is relative to the viewPort. If you use position: relative on the parent and there is no distance from the outer border of the current element (including its margin) to the top padding edge of the offsetParent, then the value will logically be zero.

Upvotes: 0

amurrell
amurrell

Reputation: 2455

Use getBoundingClientRect + window scroll position

I was having the same issue with offsetTop = 0 in some instances, but not others. For that I am still not sure why!

I had used getBoundingClientRect before with better success, so I adjusted my code to use that approach. As OP said, it gives different numbers depending on how far you have scrolled the window, but we can add that scroll position and get consistent numbers.

let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
let rectViewport = el.getBoundingClientRect();
let top = rectViewport.top + scrollTop;
  • the window.pageYOffset is deprecated but works as a "fallback" in this || method.
  • the rectViewport is our element el and utilizing getBoundingClientRect()
  • the top is the combination of the el's viewport top and scroll top

Let's imagine we were scrolled down 200ish pixels, we would see scrollTop to match that. And our element was 2000+ pixels down from the current viewport. We can combine to get 2200+ of the actual window. To see the result, combine with something fun like:

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

Upvotes: 0

user1039663
user1039663

Reputation: 1335

Calculate the correct offsetTop (same solution is valid for offsetLeft), recursing all parents until you get null with something like this:

function getOffsetTop(element) {
    return element ? (element.offsetTop + getOffsetTop(element.offsetParent)) : 0;
}

Then use that function on your code getOffsetTop(e.currentTarget) instead of getting directly e.currentTarget.offsetTop.

Upvotes: 9

Trung
Trung

Reputation: 2019

You should use the getBoundingClientRect() as follow:

var ele = document.getElementById('elementId');
var offset = ele.getBoundingClientRect();
// you can use
offset.left;
offset.top;

It works for me.

Upvotes: 18

Related Questions