Определение положения элемента относительно документа


113

Какой самый простой способ определить положение элементов относительно окна документа / тела / браузера?

Прямо сейчас я использую .offsetLeft/offsetTop, но этот метод дает вам только положение относительно родительского элемента, поэтому вам нужно определить, сколько родителей у элемента body, чтобы узнать положение относительно положения тела / окна браузера / документа.

Этот метод также слишком громоздкий.

Ответы:


59

Вы можете offsetParentперейти на верхний уровень модели DOM.

function getOffsetLeft( elem )
{
    var offsetLeft = 0;
    do {
      if ( !isNaN( elem.offsetLeft ) )
      {
          offsetLeft += elem.offsetLeft;
      }
    } while( elem = elem.offsetParent );
    return offsetLeft;
}

28
Нет, это не так, когда любой родитель (особенно элемент html !!!) имеет поля, отступы или границы.
Flash Thunder

что касается полей ... это может помочь установить размер поля на border-box ... или что-то в этом роде ... ничего, что нельзя исправить ...

Во-первых, вам нужно решить, следует ли учитывать границы и поля в соответствии с размером блока. Во-вторых, следует учитывать свернутую маржу. И, наконец, в будущем будет более сложная ситуация, которая ухудшит этот ответ.
xianshenglu

6
Почему это принятый ответ? Это устарело и плохо работает. Сделайте себе одолжение и используйте getBoundingClientRect (), как предлагается в других ответах.
Фабиан фон Эллертс

177

Вы можете попасть наверх и влево, не пересекая DOM, вот так:

function getCoords(elem) { // crossbrowser version
    var box = elem.getBoundingClientRect();

    var body = document.body;
    var docEl = document.documentElement;

    var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
    var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;

    var clientTop = docEl.clientTop || body.clientTop || 0;
    var clientLeft = docEl.clientLeft || body.clientLeft || 0;

    var top  = box.top +  scrollTop - clientTop;
    var left = box.left + scrollLeft - clientLeft;

    return { top: Math.round(top), left: Math.round(left) };
}

6
В этом ответе не учтены замещения родителей. Это только относительно области просмотра
Ники

3
@Nickey, это неправда - позиция области просмотра плюс проверки смещения прокрутки дают координаты относительно всего документа.
натчикета

1
Может быть багги на мобильных устройствах stackoverflow.com/a/32623832/962634 нужны исследования
базилик

1
Почему вы вычитаете clientTop / clientLeft?
Teemoh

1
@Teemoh clientTop / clientLeft соответствует значениям границ <html>элемента.
Raphael Rafatpanah

98

Вы можете использовать element.getBoundingClientRect()для получения позиции элемента относительно области просмотра.

Затем используйте document.documentElement.scrollTopдля вычисления смещения области просмотра.

Сумма двух даст положение элемента относительно документа:

element.getBoundingClientRect().top + document.documentElement.scrollTop

10
Относительно области просмотра не то же самое, что относительно документа. Если страница немного прокручена вниз, то верхнее положение относительно области просмотра будет меньшим числом, чем верхнее положение относительно документа.
MrVimes

14
он начинает относительно области просмотра и добавляет scrollY, чтобы получить его относительно документа.
Хоакин Куэнка Абела

2
document.documentElement.scrollTopне работает в Safari, используйте window.scrollYвместо этого
Fabian von Ellerts 08

7

Я предлагаю использовать

element.getBoundingClientRect()

как предлагается здесь вместо ручного расчета смещения через offsetLeft , offsetTop и offsetParent . как предлагается здесь. При некоторых обстоятельствах * обход вручную дает недопустимые результаты. См. Этот Plunker: http://plnkr.co/pC8Kgj

* Когда элемент находится внутри прокручиваемого родителя со статическим (= по умолчанию) позиционированием.


Вы также можете заставить вычисление смещения работать, включив в него scrollLeft и scrollTop.
Ben J

Но я нашел offsetLeftи offsetTopне принимаю во внимание преобразования CSS3, а это getBoundingClientRect()действительно так. Так что в этом случае результаты могут быть недействительными. Если вам это нужно, вы можете получить смещение элемента относительно родительского (например offsetLeft), используя (element.getBoundingClientRect().left - parent.getBoundingClientRect().left).
Ben J

должен обязательно подняться выше; эти значения гораздо более полезны, и все они в одном вызове!
mix3d 01

7

document-offset( Сторонний скрипт ) интересен, и, похоже, он использует подходы из других ответов здесь.

Пример:

var offset = require('document-offset')
var target = document.getElementById('target')
console.log(offset(target))
// => {top: 69, left: 108} 

5

Я считаю, что следующий метод является наиболее надежным при работе с крайними случаями, которые приводят к отключению offsetTop / offsetLeft.

function getPosition(element) {
    var clientRect = element.getBoundingClientRect();
    return {left: clientRect.left + document.body.scrollLeft,
            top: clientRect.top + document.body.scrollTop};
}

4

Для тех, кто хочет получить координаты x и y различных положений элемента относительно документа.

const getCoords = (element, position) => {
  const { top, left, width, height } = element.getBoundingClientRect();
  let point;
  switch (position) {
    case "top left":
      point = {
        x: left + window.pageXOffset,
        y: top + window.pageYOffset
      };
      break;
    case "top center":
      point = {
        x: left + width / 2 + window.pageXOffset,
        y: top + window.pageYOffset
      };
      break;
    case "top right":
      point = {
        x: left + width + window.pageXOffset,
        y: top + window.pageYOffset
      };
      break;
    case "center left":
      point = {
        x: left + window.pageXOffset,
        y: top + height / 2 + window.pageYOffset
      };
      break;
    case "center":
      point = {
        x: left + width / 2 + window.pageXOffset,
        y: top + height / 2 + window.pageYOffset
      };
      break;
    case "center right":
      point = {
        x: left + width + window.pageXOffset,
        y: top + height / 2 + window.pageYOffset
      };
      break;
    case "bottom left":
      point = {
        x: left + window.pageXOffset,
        y: top + height + window.pageYOffset
      };
      break;
    case "bottom center":
      point = {
        x: left + width / 2 + window.pageXOffset,
        y: top + height + window.pageYOffset
      };
      break;
    case "bottom right":
      point = {
        x: left + width + window.pageXOffset,
        y: top + height + window.pageYOffset
      };
      break;
  }
  return point;
};

использование

  • getCoords(document.querySelector('selector'), 'center')

  • getCoords(document.querySelector('selector'), 'bottom right')

  • getCoords(document.querySelector('selector'), 'top center')


2

Если вы не против использования jQuery, вы можете использовать offset()функцию. Обратитесь к документации, если вы хотите узнать больше об этой функции.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.