JavaScript getBoundingClientRect() изменяется при прокрутке

Я хочу иметь точное расстояние между Y-координатой элемента и значением Y = 0, которое я рассматриваю как верхнюю часть документа.

myElement.getBoundingClientRect().top;

Но значение getBoundingClientRect(), похоже, изменяется при прокрутке. Как я могу получить реальное расстояние между myElement и Y-координатой = 0 (верхняя часть документа)?

Ответ 1

Это потому, что getBoundingClientRect() получает значения по отношению к window (только текущая видимая часть страницы), а не document (целая страница).
Следовательно, он также учитывает прокрутку при расчете его значений В принципе, document = window + scroll

Итак, чтобы получить расстояние между myElement и Y-координатой = 0 (верхняя часть документа), вы также добавили бы значение вертикальной прокрутки:

myElement.getBoundingClientRect().top + window.scrollY;

Источник: https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect

Ответ 2

getBoundingClientRect требует немного больше внимания, чтобы избежать ошибок в 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
    };
}

Ошибки, которых следует избегать:

  • прокрутка в Android Chrome, так как Chrome Mobile 43 имеет неправильные значения для scrollY/pageYOffset (особенно когда клавиатура отображается и вы прокручиваете).

  • Пинч-зум в Microsoft IE или Edge вызывает неправильные значения для scrollY/pageYOffset.

  • Некоторые (устаревшие) браузеры не имеют высоты/ширины, например. IE8

Изменить: приведенный выше код можно упростить, просто используя document.body.getBoundingClientRect() вместо добавления div - я его не пробовал, поэтому оставляю свой ответ в его нынешнем виде. Также тело нуждается в margin:0 (reset.css обычно делает это). Этот ответ значительно упрощает код, сохраняя при этом ошибки в jQuery.offset()!