Як отримати верхнє положення елемента відносно вікна перегляду браузера?


173

Я хочу отримати позицію елемента відносно вікна перегляду браузера (вікно перегляду, в якому відображається сторінка, а не вся сторінка). Як це можна зробити в JavaScript?

Велике дякую


2
Я думаю, що це питання схоже на stackoverflow.com/questions/211703/…, який має дуже гарне рішення.
— Якоб Рунге

1
@JakobRunge, Це було "приємно" у 2013 році?
— Юліан Онофрей

1
Подумайте про прийняття рішення.
— Юліан Онофрей

Відповіді:


305

Існуючі відповіді застаріли. Нативний getBoundingClientRect()метод існує вже досить довгий час, і він робить саме те, що запитання вимагає. Крім того, він підтримується у всіх браузерах (включаючи IE 5, здається!)

На сторінці MDN :

Повернене значення - це об'єкт TextRectangle, що містить властивості лише для читання зліва, вгорі, вправо і внизу, що описують вікно рамки, у пікселях, зверху ліворуч відносно верхнього лівого огляду області перегляду .

Ви використовуєте його так:

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

3
Це може не працювати належним чином при використанні масштабування браузера (Android Chrome). Рішення від @rism ( див. Нижче ) працює в цій справі
— Дмитро

4
Добре для більшості випадків, але передбачається, що елемент не знаходиться всередині вбудованої рамки кадрів, правда? Питання задається відносно вікна браузера. El.getBoundingClientRect () поверне відносно вікна iframe, а не вікна браузера.
— cakidnyc

6
Питання задається відносно вікна браузера.
— Дмитро Дворніков

2
@Denilson getBoundingClientRect().topне в моєму IE11, він повертається 0. У вас є рішення.
— Аріф

@Arif: Вибачте, але я не можу відтворити вашу проблему. Я перевірив це на IE11 і все-таки отримав результати: codepen.io/denilsonsa/pen/ypqyXj
— Denilson Sá Maia

57

У моєму випадку, щоб бути безпечним щодо прокрутки, я додав window.scroll до рівняння:

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

Це дозволяє мені отримати реальне відносне положення елемента на документі, навіть якщо він був прокручений.


2
Хіба ви не повинні додавати позицію прокрутки, а не віднімати її?
— Юліан Онофрей

Я відповів на відповідь, але все-таки @lulian Onofrei має рацію. Відредагуйте.
— pmrotule

@Fabio getBoundingClientRect().topне в моєму IE11, він повертається 0. У вас є рішення.
— Аріф

1
@Arif window.scrollY || window.pageYOffsetможе покращити підтримку
— Фабіан фон Еллертс

@FabianvonEllerts :)
— Аріф

15

Редагувати: Додайте код для облікового запису для прокрутки сторінки.

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);
    }
}

Аргумент id - це ідентифікатор елемента, зміщення якого ви хочете. Адаптовано з допису на вигадку .


1
Дякую за вашу відповідь, але я думаю, що ви неправильно зрозуміли моє запитання, я знаю, як отримати верхню частину елемента відносно сторінки, що я намагаюся зробити, це отримати позицію відносно "вікна перегляду" (тобто вікна браузера , а не документ)
— Waleed Eissa

Вибачте, що ваше використання "viewport" кинуло мене. Отже, ви кажете, що хочете обліковувати хром браузера, тобто панель інструментів закладок, панель розташування тощо?
— Дерек Свінглі

Ні, просто вікно, через яке ви бачите сторінку. Якщо сторінка прокручується, це буде відрізнятися від верху документа, інакше вони однакові.
— Waleed Eissa

Добре, я розумію. Не знаю, як це зробити ... відредагую свою відповідь, якщо я щось придумаю.
— Дерек Свінглі

Я зробив код вище трохи потворнішим, але він працює ... використовуйте offsetParent.scrollTop
— Дерек

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

Це, здається, обчислюється вгорі документа, а не в області перегляду
— Скотт Леонард

6

Ви можете спробувати:

node.offsetTop - window.scrollY

Він працює в Opera з визначеним метатегом перегляду.


7
Якщо я правильно розумію документацію , offsetTopстосується найближчого розміщеного елемента. Який, залежно від структури сторінки, може бути або не бути кореневим елементом.
— Denilson Sá Maia

5

jQuery реалізує це досить елегантно. Якщо ви подивитесь на джерело jQuery offset, ви побачите, що це в основному як воно реалізовано:

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

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

2

Функція на цій сторінці поверне прямокутник з верхніми, лівими, координатами висоти та ширини переданого елемента відносно порту перегляду браузера.

    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;
}

2
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;
}

джерело


1

Дякую за всі відповіді. Здається, у прототипу вже є функція, яка виконує цю функцію (page ()). Переглядаючи вихідний код функції, я виявив, що він спочатку обчислює положення зміщення елемента відносно сторінки (тобто верхній частині документа), а потім віднімає з цього scrollTop. Детальнішу інформацію див. У вихідному коді прототипу.


Гарне рішення. Можливо, найкраще працювати з однією з основних бібліотек, оскільки вони швидше дають однаковий результат у веб-переглядачах. Якщо вам цікаво, перевірте мою відповідь. Код там зробить це, але я поняття не маю, як він утримуватиметься в браузерах.
— Дерек Свінглі

1

Я припускаю, що btn1на веб-сторінці існує елемент, який має ідентифікатор існування, а також включений jQuery. Це працює у всіх сучасних браузерах Chrome, FireFox, IE> = 9 та Edge. jQuery використовується лише для визначення позиції щодо документа.

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

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

1
jQuery - це JavaScript. Я вважаю, ви мали на увазі "це не 100% ваніль / чистий JS".
— голод

Так, це я мав на увазі.
— Суніль

1

Іноді getBoundingClientRect()значення властивості об'єкта показує 0 для IE. У цьому випадку ви повинні встановити display = 'block'елемент. Ви можете використовувати код нижче для всіх браузерів для компенсації.

Розширення функціональності jQuery:

(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));

Використання:

var elementOffset = $("#" + elementId).weOffset();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.