Получить позицию (X, Y) элемента HTML относительно окна браузера

Я хочу знать, как получить положение X и Y элементов HTML, таких как img и div, в JavaScript относительно окна браузера.


person Community    schedule 14.01.2009    source источник
comment
Я использовал эти 7 строк кода, которые работают во всех браузерах с несоответствиями в ie5,6,7 (я не помню, чтобы у меня были какие-либо пробоемы ... может быть тип документа) ... quirksmode.org/js/findpos.html, и я много лет использовал его. Может быть, кто-нибудь может указать на недостатки, если таковые имеются.   -  person Jayapal Chandran    schedule 02.04.2015
comment
@AnthonyWJones, я полагаю, вам нужно было педантичное удовольствие, но очевидно, как всегда, когда не указано иное, что OP относится к наиболее общему случаю или относится к координатам окна браузера.   -  person Motes    schedule 26.05.2015
comment
Ответ @ AndyE - явный победитель - не могли бы вы отметить принятый ответ, чтобы другим не пришлось читать 10 других ответов, чтобы добраться до него?   -  person mindplay.dk    schedule 16.03.2016
comment
Здравствуйте, мистер Грег. Можете ли вы решить эту проблему? Я только что опубликовал свою ссылку. Щелкните ее один раз stackoverflow.com/questions/41743667/ < / а>   -  person Lavaraju    schedule 23.01.2017
comment
@Mote, нет, это не так уж и очевидно. Оставьте в стороне умозаключения, субъективность и ложные аксиомы. Это может быть относительно области просмотра или верхней части страницы (также известный как document.documentElement).   -  person Andre Figueiredo    schedule 22.10.2017
comment
По умолчанию самое общее - это не вывод, это логическая последовательность, так что это будет относиться к окну или верхней части страницы может быть термином, как вы его выразили. В теории игр это кодифицировано как понятие, называемое точкой Шеллинга. Обязательно укажите, когда вы не имеете в виду самый общий случай.   -  person Motes    schedule 22.10.2017
comment
Дело в том, что очевидное для одних не очевидно для других. Даже если теоретически мы знаем, что именно так, благодаря эмпирическим знаниям, ясность здесь никому не повредит, особенно тем, кто только начал программировать.   -  person Andre Figueiredo    schedule 22.01.2019


Ответы (27)


Правильный подход - использовать element.getBoundingClientRect():

var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);

Internet Explorer поддерживает это с тех пор, как вы, вероятно, заботитесь о нем, и, наконец, он был стандартизирован в Представления CSSOM. Все остальные браузеры приняли его давно.

Некоторые браузеры также возвращают свойства высоты и ширины, хотя это нестандартно. Если вас беспокоит совместимость старых браузеров, проверьте исправления в этом ответе на предмет оптимизированной деградирующей реализации.

Значения, возвращаемые element.getBoundingClientRect(), относятся к области просмотра. Если вам это нужно относительно другого элемента, просто вычтите один прямоугольник из другого:

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

alert('Element is ' + offset + ' vertical pixels from <body>');
person Andy E    schedule 09.07.2012
comment
очень интересная статья о координатах JS. Эта статья нигде не упоминается на SO, она должна .. - person Breaking not so bad; 19.02.2014

Библиотеки идут на все, чтобы получить точные смещения для элемента.
вот простая функция, которая выполняет свою работу в любых обстоятельствах, которые я пробовал.

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}
var x = getOffset( document.getElementById('yourElId') ).left; 
person meouw    schedule 14.01.2009
comment
изменить: el = el.parentNode на: el = el.offsetParent; и, похоже, теперь он работает для вложенных фреймов ... Я думаю, что вы это хотели? - person Adam; 30.07.2009

Эта функция возвращает позицию элемента относительно всего документа (страницы):

function getOffset(el) {
  const rect = el.getBoundingClientRect();
  return {
    left: rect.left + window.scrollX,
    top: rect.top + window.scrollY
  };
}

Используя это, мы можем получить позицию X:

getOffset(element).left

... или положение Y:

getOffset(element).top

Версия TypeScript:

export type ElementOffset = {
  left: number;
  top: number
};

/**
 * Returns an element's position relative to the whole document (page).
 *
 * If the element does not exist, returns O/O (top-left window corner).
 *
 * @example getOffset(document.getElementById('#element'));
 *
 * @param el
 * @see https://stackoverflow.com/a/28222246/2391795
 */
export const getElementOffset = (el: Element | null): ElementOffset => {
  const rect = el?.getBoundingClientRect();

  return {
    left: (rect?.left || 0) + window?.scrollX,
    top: (rect?.top || 0) + window?.scrollY,
  };
};

export default getElementOffset;
person Adam Grant    schedule 29.01.2015

Если вы хотите, чтобы это было сделано только в javascript, вот несколько однострочников с использованием _ 1_

window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y

window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X

Первая строка вернет offsetTop, скажем, Y относительно документа. Вторая строка вернет offsetLeft, скажем, X относительно документа.

getBoundingClientRect() - это функция JavaScript, которая возвращает положение элемента относительно области просмотра. окна.

person Mustkeem K    schedule 24.09.2018

Элементы HTML в большинстве браузеров будут иметь: -

offsetLeft
offsetTop

Они определяют положение элемента относительно его ближайшего родителя, у которого есть макет. К этому родительскому элементу часто можно получить доступ через свойство offsetParent.

IE и FF3 имеют

clientLeft
clientTop

Эти свойства менее распространены, они определяют положение элемента вместе с его родительской клиентской областью (заполненная область является частью клиентской области, а граница и поля - нет).

person AnthonyWJones    schedule 14.01.2009

Если страница включает - по крайней мере - любой «DIV», функция, заданная meouw, выбрасывает значение «Y» за пределы текущей страницы. Чтобы найти точное положение, вам нужно обработать как offsetParent, так и parentNode.

Попробуйте приведенный ниже код (он проверен на FF2):


var getAbsPosition = function(el){
    var el2 = el;
    var curtop = 0;
    var curleft = 0;
    if (document.getElementById || document.all) {
        do  {
            curleft += el.offsetLeft-el.scrollLeft;
            curtop += el.offsetTop-el.scrollTop;
            el = el.offsetParent;
            el2 = el2.parentNode;
            while (el2 != el) {
                curleft -= el2.scrollLeft;
                curtop -= el2.scrollTop;
                el2 = el2.parentNode;
            }
        } while (el.offsetParent);

    } else if (document.layers) {
        curtop += el.y;
        curleft += el.x;
    }
    return [curtop, curleft];
};

person Refik Ayata    schedule 12.08.2010
comment
как и в случае с другими решениями, даже с FF 24.4 приведенный выше код не работает, когда ширина границ существует как часть макета позиционирования. - person rob; 13.05.2014
comment
Ты спасатель. Я сейчас прорабатываю несколько довольно глубоких ошибок GWT, и добавление их в метод JSNI решает все мои проблемы !! - person Will Byrne; 11.06.2015

Вы можете добавить два свойства к Element.prototype, чтобы получить верхний / левый угол любого элемента.

Object.defineProperty( Element.prototype, 'documentOffsetTop', {
    get: function () { 
        return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop : 0 );
    }
} );

Object.defineProperty( Element.prototype, 'documentOffsetLeft', {
    get: function () { 
        return this.offsetLeft + ( this.offsetParent ? this.offsetParent.documentOffsetLeft : 0 );
    }
} );

Это называется так:

var x = document.getElementById( 'myDiv' ).documentOffsetLeft;

Вот демонстрация, сравнивающая результаты с offset().top и .left jQuery: http://jsfiddle.net/ThinkingStiff/3G7EZ/

person ThinkingStiff    schedule 14.01.2012
comment
изменение Element.prototype обычно считается плохой идеей. Это приводит к тому, что код очень сложно поддерживать. Кроме того, этот код не учитывает прокрутку. - person Jared Forsyth; 23.06.2015

Чтобы получить позицию относительно страницы эффективно и без использования рекурсивной функции: (также включает IE)

var element = document.getElementById('elementId'); //replace elementId with your element's Id.
var rect = element.getBoundingClientRect();
var elementLeft,elementTop; //x and y
var scrollTop = document.documentElement.scrollTop?
                document.documentElement.scrollTop:document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft?                   
                 document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;
person Abdul Rahim Haddad    schedule 26.07.2013
comment
Включение всех важных scrollTop / scrollLeft делает этот ответ немного более правильным. - person scunliffe; 07.12.2014

Как насчет того, чтобы передать идентификатор элемента, и он вернет left или top, мы также можем объединить их:

1) найти слева

function findLeft(element) {
  var rec = document.getElementById(element).getBoundingClientRect();
  return rec.left + window.scrollX;
} //call it like findLeft('#header');

2) найти верх

function findTop(element) {
  var rec = document.getElementById(element).getBoundingClientRect();
  return rec.top + window.scrollY;
} //call it like findTop('#header');

или 3) найдите вместе левую и верхнюю часть

function findTopLeft(element) {
  var rec = document.getElementById(element).getBoundingClientRect();
  return {top: rec.top + window.scrollY, left: rec.left + window.scrollX};
} //call it like findTopLeft('#header');
person Alireza    schedule 22.05.2017

jQuery .offset () получит текущие координаты первого элемента или установит координаты каждого элемента в наборе совпадающих элементов относительно документа.

person akauppi    schedule 18.08.2010
comment
По какой-то причине он не дает таких же результатов в IE по сравнению с другими браузерами. Я думаю, что в IE он задает положение относительно окна, поэтому, если вы прокрутите, вы получите разные результаты в IE по сравнению с другими - person Abdul Rahim Haddad; 10.08.2013
comment
offset () сбивает с толку масштабированием, по крайней мере, в Android Chrome, поэтому бесполезен. stackoverflow.com/a/11396681/1691517 показывает устойчивый к масштабированию способ. - person Timo Kähkönen; 31.05.2015

Возможно, вам будет удобнее использовать фреймворк JavaScript, который имеет функции для возврата такой информации (и многого другого!) Независимо от браузера. Вот несколько:

С помощью этих фреймворков вы можете сделать что-то вроде: $('id-of-img').top, чтобы получить координату y-пикселя изображения.

person Shalom Craimer    schedule 14.01.2009

/**
 *
 * @param {HTMLElement} el
 * @return {{top: number, left: number}}
 */
function getDocumentOffsetPosition(el) {
    var position = {
        top: el.offsetTop,
        left: el.offsetLeft
    };
    if (el.offsetParent) {
        var parentPosition = getDocumentOffsetPosition(el.offsetParent);
        position.top += parentPosition.top;
        position.left += parentPosition.left;
    }
    return position;
}

Благодарим ThinkingStiff за ответ, это всего лишь другая версия.

person Văn Quyết    schedule 29.08.2019

Я взял ответ @meouw, добавил в clientLeft, который позволяет использовать границу, а затем создал три версии:

getAbsoluteOffsetFromBody - аналогично @meouw, получает абсолютную позицию относительно тела или элемента html документа (в зависимости от режима причуд)

getAbsoluteOffsetFromGivenElement - возвращает абсолютную позицию относительно данного элемента (relativeEl). Обратите внимание, что данный элемент должен содержать элемент el, иначе он будет вести себя так же, как getAbsoluteOffsetFromBody. Это полезно, если у вас есть два элемента, содержащихся в другом (известном) элементе (возможно, несколько узлов в дереве узлов), и вы хотите сделать их одинаковыми.

getAbsoluteOffsetFromRelative - возвращает абсолютную позицию относительно первого родительского элемента с position: relative. Это похоже на getAbsoluteOffsetFromGivenElement по той же причине, но будет работать только до первого совпадающего элемента.

getAbsoluteOffsetFromBody = function( el )
{   // finds the offset of el from the body or html element
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromGivenElement = function( el, relativeEl )
{   // finds the offset of el from relativeEl
    var _x = 0;
    var _y = 0;
    while( el && el != relativeEl && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromRelative = function( el )
{   // finds the offset of el from the first parent with position: relative
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
        if (el != null)
        {
            if (getComputedStyle !== 'undefined')
                valString = getComputedStyle(el, null).getPropertyValue('position');
            else
                valString = el.currentStyle['position'];
            if (valString === "relative")
                el = null;
        }
    }
    return { top: _y, left: _x };
}

Если у вас по-прежнему возникают проблемы, особенно связанные с прокруткой, вы можете попробовать посмотреть http://www.greywyvern.com/?post=331 - Я заметил по крайней мере один сомнительный код в getStyle, который должен работать, если предположить, что браузеры работают, но не тестировал остальное.

person James Carlyle-Clarke    schedule 01.12.2015
comment
Интересно ... но на Edge getAbsoluteOffsetFromBody (element) .top возвращает другое значение при прокрутке, в Chrome оно остается неизменным при прокрутке. Похоже, Edge корректирует положение прокрутки. Когда элемент прокручивается вне поля зрения, я получаю отрицательное значение. - person Norman; 13.01.2018
comment
getAbsoluteOffsetFromRelative сделал мой день лучше, мне пришлось воспроизвести всплывающую подсказку начальной загрузки без Javascript начальной загрузки, это мне очень помогло. - person Nolyurn; 13.08.2018
comment
На всякий случай, если Meouw изменит свое имя пользователя, ссылка для ответа: stackoverflow.com/a/442474/3654837. (Я не хочу натыкаться на эту старую ветку, так что да, я оставил комментарий) - person Mukyuu; 10.01.2020

при использовании jQuery отлично подходит подключаемый модуль размеров, который позволяет указать именно то, что вы хотите.

e.g.

Относительное положение, абсолютное положение, абсолютное положение без заполнения, с заполнением ...

Это продолжается, давайте просто скажем, что вы можете многое с этим сделать.

Плюс к этому бонус от использования jQuery - это легкий размер файла и простота использования, вы не вернетесь к JavaScript без него впоследствии.

person John_    schedule 14.01.2009

Если вы используете jQuery, это может быть простое решение:

<script>
  var el = $("#element");
  var position = el.position();
  console.log( "left: " + position.left + ", top: " + position.top );
</script>
person Adam Boostani    schedule 16.04.2013

Разница между маленьким и маленьким

function getPosition( el ) {
    var x = 0;
    var y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
    x += el.offsetLeft - el.scrollLeft;
    y += el.offsetTop - el.scrollTop;
    el = el.offsetParent;
    }
    return { top: y, left: x };
}

Посмотрите пример координат: http://javascript.info/tutorial/coordinates

person KingRider    schedule 25.08.2016
comment
К сожалению, это не работает для всех элементов, которые можно найти в современном HTML-документе. Например, встроенные элементы <svg> не имеют свойств offsetLeft, offsetTop и offsetParent. - person Jonathan Eunice; 19.10.2016
comment
Это просто DIV или IMG, а не SVG. Посмотреть Посмотрите пример координат? вы можете найти объект svg в вызове позиции getOffsetRect, попробовать и получить зависимость от объекта. - person KingRider; 19.10.2016

Самый чистый подход, который я нашел, - это упрощенная версия техники, используемой jQuery offset. Как и в некоторых других ответах, он начинается с getBoundingClientRect; затем он использует window и documentElement для настройки положения прокрутки, а также такие вещи, как поле на body (часто по умолчанию).

var rect = el.getBoundingClientRect();
var docEl = document.documentElement;

var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

var els = document.getElementsByTagName("div");
var docEl = document.documentElement;

for (var i = 0; i < els.length; i++) {

  var rect = els[i].getBoundingClientRect();

  var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
  var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

  els[i].innerHTML = "<b>" + rectLeft + ", " + rectTop + "</b>";
}
div {
  width: 100px;
  height: 100px;
  background-color: red;
  border: 1px solid black;
}
#rel {
  position: relative;
  left: 10px;
  top: 10px;
}
#abs {
  position: absolute;
  top: 250px;
  left: 250px;
}
<div id="rel"></div>
<div id="abs"></div>
<div></div>

person James Montagne    schedule 04.11.2014

Это лучший код, который мне удалось создать (работает и в iframe, в отличие от смещения jQuery ()). Кажется, у webkit немного другое поведение.

На основе комментария meouw:

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        // chrome/safari
        if ($.browser.webkit) {
            el = el.parentNode;
        } else {
            // firefox/IE
            el = el.offsetParent;
        }
    }
    return { top: _y, left: _x };
}
person Ron Reiter    schedule 10.09.2011
comment
Обратите внимание, что вам понадобится jQuery, чтобы использовать $.browser.webkit; Вам нужно будет поиграть с navigator.userAgent, чтобы сделать то же самое с чистым JavaScript. - person S P; 07.03.2012
comment
$ .browser больше не доступен в последней версии jQuery - person Gus; 12.01.2014
comment
к сожалению, даже с FF 24.4 приведенный выше код не работает, когда ширина границ существует как часть макета позиционирования. - person rob; 13.05.2014

Хотя это, скорее всего, будет потеряно в нижней части стольких ответов, лучшие решения здесь не работали для меня.
Насколько я мог сказать, ни один из других ответов не помог бы.

Ситуация:
На странице HTML5 у меня было меню, которое представляло собой элемент навигации внутри заголовка (не заголовок THE, а заголовок в другом элементе).
I хотел, чтобы навигация оставалась наверху, когда пользователь прокручивает ее, но до этого заголовок был позиционирован абсолютно (так что я мог немного перекрыть что-то еще).
Приведенные выше решения никогда не вызывали изменения, потому что .offsetTop был не изменится, так как это был элемент с абсолютной позицией. Кроме того, свойство .scrollTop было просто вершиной самого верхнего элемента ... то есть 0 и всегда будет 0.
Любые тесты, которые я проводил с использованием этих двух (и то же самое с результатами getBoundingClientRect), не скажут мне, если верхняя часть панели навигации когда-либо прокручивалась до верхней части просматриваемой страницы (опять же, как сообщается в консоли, они просто оставались теми же номерами во время прокрутки).

Решение
Для меня решение использовало

window.visualViewport.pageTop

Значение свойства pageTop отражает видимую часть экрана, что позволяет мне отслеживать, где находится элемент по отношению к границам видимой области.

Наверное, нет необходимости говорить, что каждый раз, когда я имею дело с прокруткой, я собираюсь использовать это решение, чтобы программно реагировать на движение прокручиваемых элементов.
Надеюсь, это поможет кому-то другому.
ВАЖНОЕ ПРИМЕЧАНИЕ: Кажется, это работает в Chrome и Opera. в настоящее время и определенно не в Firefox (6-2018) ... пока Firefox не поддерживает visualViewport, я рекомендую НЕ использовать этот метод (и я надеюсь, что они скоро сделают это ... он имеет гораздо больше смысла, чем остальные).


ОБНОВЛЕНИЕ:
Обратите внимание на это решение.
Хотя я все еще считаю то, что я обнаружил, очень ценным для ситуаций, в которых «... программно реагируют на движение прокручиваемых элементов». применимо. Лучшим решением возникшей у меня проблемы было использование CSS для установки position: sticky на элементе. Используя липкий, вы можете оставить элемент наверху без использования javascript (ПРИМЕЧАНИЕ: иногда это не сработает так же эффективно, как изменение элемента на фиксированный, но для большинства применений липкий подход, вероятно, будет лучше)

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

  let bodyElement = document.getElementsByTagName('body')[0];
  let elementToTrack = bodyElement.querySelector('.trackme');
  trackedObjPos = elementToTrack.getBoundingClientRect().top;
  if(trackedObjPos > 264)
  {
    bodyElement.style.cssText = '';
  }

Надеюсь, этот ответ теперь более полезен.

person MER    schedule 24.10.2017
comment
это, скорее всего, будет в верхней части множества ответов, когда вы нажмете активный, чтобы отсортировать ответы - person lucchi; 01.06.2018
comment
@lucchi: D ну, я полагаю, я мог бы удалить текст @ вверху ... хотя я только что наткнулся на это снова и понял, что нашел лучшее решение для моей собственной проблемы ... хотя мой ответ скорее сноска к более полным ответам. Я подозреваю, что мои требования, возможно, были не настолько распространены, что другие ответы не сработали для меня? - person MER; 01.06.2018
comment
В любом случае, я ценю ваш ответ, я просто хотел сказать вам, что любой желающий будет знать, что вы написали что-то новое. Ты не одинок.... - person lucchi; 02.06.2018

Чтобы получить общее смещение элемента, вы можете рекурсивно суммировать все родительские смещения:

function getParentOffsets(el): number {
if (el.offsetParent) {
    return el.offsetParent.offsetTop + getParentOffset(el.offsetParent);
} else {
    return 0;
}
}

с этой служебной функцией общее смещение сверху элемента dom равно:

el.offsetTop + getParentOffsets(el);
person Kevin K.    schedule 01.03.2019
comment
Этот ответ выглядит так, как хотелось бы, за исключением того, что я получаю сообщение об ошибке Uncaught ReferenceError: getParentOffset не определен. Отсутствует буква "s", не так ли? Поэтому я изменил строку возврата функции, добавив букву «s» в «getParentOffset». Сейчас ошибок нет, но меня беспокоит, зная, что это была ошибка ... - person kenneth558; 18.02.2021

Я сделал это так, чтобы он был перекрестно совместим со старыми браузерами.

// For really old browser's or incompatible ones
    function getOffsetSum(elem) {
        var top = 0,
            left = 0,
            bottom = 0,
            right = 0

         var width = elem.offsetWidth;
         var height = elem.offsetHeight;

        while (elem) {
            top += elem.offsetTop;
            left += elem.offsetLeft;
            elem = elem.offsetParent;
        }

         right = left + width;
         bottom = top + height;

        return {
            top: top,
            left: left,
            bottom: bottom,
            right: right,
        }
    }

    function getOffsetRect(elem) {
        var box = elem.getBoundingClientRect();

        var body = document.body;
        var docElem = document.documentElement;

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

        var clientTop = docElem.clientTop;
        var clientLeft = docElem.clientLeft;


        var top = box.top + scrollTop - clientTop;
        var left = box.left + scrollLeft - clientLeft;
        var bottom = top + (box.bottom - box.top);
        var right = left + (box.right - box.left);

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

    function getOffset(elem) {
        if (elem) {
            if (elem.getBoundingClientRect) {
                return getOffsetRect(elem);
            } else { // old browser
                return getOffsetSum(elem);
            }
        } else
            return null;
    }

Подробнее о координатах в JavaScript здесь: http://javascript.info/tutorial/coordinates

person Bojan Kseneman    schedule 15.03.2015

Я успешно использовал решение Andy E для размещения модального окна bootstrap 2 в зависимости от того, на какую ссылку в строке таблицы нажимает пользователь. Эта страница представляет собой страницу Tapestry 5, а приведенный ниже javascript импортируется в класс страницы java.

javascript:

function setLinkPosition(clientId){
var bodyRect = document.body.getBoundingClientRect(),
elemRect = clientId.getBoundingClientRect(),
offset   = elemRect.top - bodyRect.top;
offset   = offset + 20;
$('#serviceLineModal').css("top", offset);

}

Мой модальный код:

<div id="serviceLineModal" class="modal hide fade add-absolute-position" data-backdrop="static" 
 tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="top:50%;">
<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
    <h3 id="myModalLabel">Modal header</h3>
</div>

<div class="modal-body">
    <t:zone t:id="modalZone" id="modalZone">
        <p>You selected service line number: ${serviceLineNumberSelected}</p>
    </t:zone>
</div>

<div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <!-- <button class="btn btn-primary">Save changes</button> -->
</div>

The link in the loop:

<t:loop source="servicesToDisplay" value="service" encoder="encoder">
<tr style="border-right: 1px solid black;">       
    <td style="white-space:nowrap;" class="add-padding-left-and-right no-border"> 
        <a t:type="eventLink" t:event="serviceLineNumberSelected" t:context="service.serviceLineNumber" 
            t:zone="pageZone" t:clientId="modalLink${service.serviceLineNumber}"
            onmouseover="setLinkPosition(this);">
            <i class="icon-chevron-down"></i> <!-- ${service.serviceLineNumber} -->
        </a>
    </td>

И код Java в классе страницы:

void onServiceLineNumberSelected(String number){
    checkForNullSession();
    serviceLineNumberSelected = number;
    addOpenServiceLineDialogCommand();
    ajaxResponseRenderer.addRender(modalZone);
}

protected void addOpenServiceLineDialogCommand() {
    ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
        @Override
        public void run(JavaScriptSupport javascriptSupport) {
            javascriptSupport.addScript("$('#serviceLineModal').modal('show');");
        }
    });
}

Надеюсь, это кому-то поможет, этот пост помог.

person Mark Espinoza    schedule 23.10.2014
comment
Этот js-код мне помог, у меня есть старое приложение webforms, использующее несколько заполнителей, вставляющее страницы .aspx, и я не мог понять, как добавить к нему всплывающее окно, которое я создавал, чтобы поместить его в область просмотра, потому что все дерево DOM взломано с множеством заполнителей и неправильной разметкой. Мне было нужно использовать body.getBoundingClientRect (), а затем использовать его верхнюю часть для позиционирования. Спасибо. - person Brad Martin; 15.08.2015

После долгих исследований и испытаний, похоже, это сработало.

function getPosition(e) {
    var isNotFirefox = (navigator.userAgent.toLowerCase().indexOf('firefox') == -1);
    var x = 0, y = 0;
    while (e) {
        x += e.offsetLeft - e.scrollLeft + (isNotFirefox ? e.clientLeft : 0);
        y += e.offsetTop - e.scrollTop + (isNotFirefox ? e.clientTop : 0);
        e = e.offsetParent;
    }
    return { x: x + window.scrollX, y: y + window.scrollY };
}

см. http://jsbin.com/xuvovalifo/edit?html,js,output

person kernowcode    schedule 17.06.2015

Просто подумал, что я тоже выкину это там.
Мне не удалось протестировать его в старых браузерах, но он работает в последней из лучших 3. :)

Element.prototype.getOffsetTop = function() {
    return ( this.parentElement )? this.offsetTop + this.parentElement.getOffsetTop(): this.offsetTop;
};
Element.prototype.getOffsetLeft = function() {
    return ( this.parentElement )? this.offsetLeft + this.parentElement.getOffsetLeft(): this.offsetLeft;
};
Element.prototype.getOffset = function() {
    return {'left':this.getOffsetLeft(),'top':this.getOffsetTop()};
};
person Duncan    schedule 12.10.2014

Это просто, как две строчки в JS:

var elem = document.getElementById("id");    
alert(elem.getBoundingClientRect());
person Talha Rafique    schedule 18.07.2020
comment
Этот ответ неполный и ничего не добавляет к предыдущим ответам. - person mfluehr; 02.12.2020

Поскольку разные браузеры по-разному отрисовывают границы, отступы, поля и т. Д. Я написал небольшую функцию для извлечения верхней и левой позиции определенного элемента в каждом корневом элементе, который вы хотите в точном измерении:

function getTop(root, offset) {
    var rootRect = root.getBoundingClientRect();
    var offsetRect = offset.getBoundingClientRect();
    return offsetRect.top - rootRect.top;
}

Для возврата в левую позицию необходимо вернуть:

    return offsetRect.left - rootRect.left;
person samadadi    schedule 08.01.2015

Получить позицию div относительно left и Top

  var elm = $('#div_id');  //get the div
  var posY_top = elm.offset().top;  //get the position from top
  var posX_left = elm.offset().left; //get the position from left 
person Vishal Kumar    schedule 09.04.2018
comment
Я проголосовал против, потому что нижний и правый угол не являются свойствами offset () - person MacroMan; 08.05.2018
comment
@MacroMan, я уважаю ваше решение, но я уже объяснил в тексте, что нижний и правый код не тестируется .. Кроме того, я обновлю свой код очень скоро. - person Vishal Kumar; 08.05.2018
comment
Я думаю, что это el.offsetTop и el.offsetLeft (OP ничего не говорит о jQuery ... Я не уверен, почему в вашем ответе также используется jQuery ...) - person mesqueeb; 10.07.2018