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

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

14.01.2009 09:35:03
Относительно чего?
AnthonyWJones 14.01.2009 09:39:27
я использовал эти 7 строк кода, который работает во всех браузерах с расхождениями в ie5,6,7 (я не помню, чтобы у меня был какой-то пробоем ... может быть, это тип документа) ... quirksmode.org/js/findpos. HTML, и я использовал его много лет. может быть кто-то может указать недостатки, если таковые имеются.
Jayapal Chandran 2.04.2015 15:27:50
@AnthonyWJones, я полагаю, вам нужно было педантичное удовольствие, но очевидно, как всегда, когда не указано, что OP относится к наиболее общему случаю или относится к координатам окна браузера.
Motes 26.05.2015 20:29:25
@ Mote, нет, это не так очевидно. Оставьте вывод, субъективность и ложные аксиомы в стороне. Это может быть относительно области просмотра или верхней части страницы (также известный как document.documentElement).
Andre Figueiredo 22.10.2017 02:27:34
По умолчанию самое общее - это не логический вывод, это логическая последовательность, так что она будет относиться к окну, или «верх страницы» может быть термином, как вы его выразили. В теории игр она кодифицируется как концепция, называемая точкой Шеллинга. Обязательно укажите, когда вы не имеете в виду самый общий случай.
Motes 22.10.2017 18:45:13
26 ОТВЕТОВ

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

offsetLeft
offsetTop

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

IE и FF3 имеют

clientLeft
clientTop

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

46
14.01.2009 09:43:14

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

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

16
9.12.2010 07:56:38
@Costa Все они используют эти виды функций, хотя это развивающееся поле, поскольку разные браузеры по-разному соответствуют спецификации. Большая часть кода посвящена исправлению ошибок. Вы действительно должны смотреть на исходный код.
Shalom Craimer 27.03.2013 17:38:08
@scraimer: jQuery и YUI НЕ являются фреймворками !!! Это библиотеки ! Это не тоже самое. Ссылаясь на jquery.com : «jQuery - это быстрая, небольшая и многофункциональная библиотека JavaScript ». Ссылаясь на yuilibrary.com (вы также можете увидеть «волшебное» слово в URL-адресе ...): «YUI - это бесплатная библиотека JavaScript и CSS с открытым исходным кодом для создания многофункциональных интерактивных веб-приложений».
Sk8erPeter 9.05.2013 11:34:50
Таким образом, вы должны использовать огромные библиотеки только для этой простой задачи? Не обязательно. Я ненавижу, что каждый раз, когда я хочу что-то сделать с js, я получаю эти решения jQuery. JQuery это не JS!
Opptatt Jobber 11.10.2013 19:14:50
@ OpppattJobber Я согласен ... JQuery не является JavaScript. Он опирается на Javascript, но это совершенно другой язык программирования.
Nick Manning 27.03.2014 00:31:35
@NickManning Это не новый язык, это уровень абстракции для DOM, который избавляет от необходимости записывать обходные пути совместимости и производительности непосредственно в ваш код. Если вы не используете jQuery, вы все равно должны использовать какой-либо слой абстракции.
ginman 4.04.2014 15:01:14

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

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; 
321
27.09.2015 01:42:32
изменить: el = el.parentNode на: el = el.offsetParent; и, похоже, теперь работает для вложенных фреймов ... Я думаю, это то, что вы хотели?
Adam 29.07.2009 20:19:03
Это решение является неполным. Попробуйте поставить толстую границу на div и вложите его несколько раз. В любой версии Firefox (2-5) он будет отключен по ширине (-ям) границы (даже в режиме соответствия стандартам).
ck_ 5.08.2011 05:21:30
нет ли более чистого способа сделать это, например, функции el.totalOffsetLeft и totalOffsetTop? jQuery, безусловно, имеет эту опцию, но обидно, что нет официального метода для этого, нужно ли ждать DOM4? Я создаю HTML5-приложение холста, поэтому я думаю, что лучшим решением было бы вставить элемент холста в iframe, чтобы я мог получить реальные координаты с clientX и clientY, когда мы нажимаем на элемент.
baptx 30.05.2012 17:04:37
Итак, @Adam и meouw, ты хочешь сказать, что первый блок кода неправильный? Тогда почему бы не удалить это вообще? (Этот вопрос видел довольно много зрителей за эти годы; возможно, было бы неплохо убрать вещи, если они не правы?)
Arjan 11.08.2012 23:35:34
@baptx: я знаю, что это поздний ответ, но я не видел твой комментарий раньше. Смотрите мой ответ ниже, чтобы найти альтернативу, более совместимую со стандартами - вам даже не нужен запасной код, так как браузеры уже давно его поддерживают.
Andy E 8.02.2013 18:49:53

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

например

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

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

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

8
14.07.2011 21:37:31

Если страница содержит, по крайней мере, какой-либо «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];
};
35
7.08.2018 21:58:29
как и в других решениях даже с FF 24.4, вышеприведенный код не работает, когда ширины границ существуют как часть макета позиционирования.
rob 12.05.2014 20:46:42
Вы спасатель. Я работаю над некоторыми довольно глубокими ошибками GWT прямо сейчас, и добавление этого в метод JSNI решает все мои проблемы !!
Will Byrne 10.06.2015 21:27:03

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

14
24.02.2017 00:49:49
По некоторым причинам он не дает такие же результаты в IE по сравнению с другими браузерами. Я думаю, что в IE это дает положение относительно окна, поэтому, если вы прокрутите, в IE вы получите другие результаты по сравнению с другими
Abdul Rahim Haddad 10.08.2013 16:19:34
offset () сбивает с толку, по крайней мере, в Android Chrome, поэтому он бесполезен. stackoverflow.com/a/11396681/1691517 показывает толерантный к масштабированию способ.
Timo Kähkönen 31.05.2015 18:45:06

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

На основании комментария Мёу:

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 };
}
7
10.09.2011 17:05:08
Обратите внимание, что вам нужно jQueryиспользовать $.browser.webkit; Вам нужно будет поиграться, navigator.userAgentчтобы сделать то же самое с чистым JavaScript.
S P 7.03.2012 02:47:29
$ .browser больше не доступен в последней версии jQuery
Gus 12.01.2014 18:22:38
к сожалению, даже с FF 24.4 приведенный выше код не работает, когда ширины границ существуют как часть компоновки позиционирования.
rob 12.05.2014 20:43:46

Вы можете добавить два свойства, чтобы 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;

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

35
23.02.2017 23:31:55
Модификация Element.prototypeобычно считается плохой идеей . Это приводит к очень сложному обслуживанию кода. Кроме того, этот код не учитывает прокрутку.
Jared Forsyth 22.06.2015 21:58:30

Правильный подход заключается в использовании 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>');
1767
10.01.2018 13:44:57
Очень интересная статья на JS координаты . Эта статья нигде не упоминается на SO, она должна ..
Ring Ø 19.02.2014 10:55:52
Не работает ... это 8 пикселей по вертикали и горизонтали, из-за поля в 8px в теле. Решение Меоу отлично работает. Если хотите, у меня есть небольшой тест, чтобы продемонстрировать проблему.
CpnCrunch 1.07.2014 02:30:23
На самом деле, я думаю, что это зависит от того, что вы на самом деле хотите получить координаты. Вопрос немного двусмысленный. Ваш ответ верен, если вы просто хотите получить координаты относительно области просмотра или относительно элемента body, но это не поможет вам в том случае, если вы хотите установить абсолютную позицию элемента (что, как я думаю, требуется большинству людей) , Ответ meouw также не даст вам этого, если вы не удалите биты '-scrollLeft' и '-scrollTop'.
CpnCrunch 3.07.2014 17:58:22
@CpnCrunch: теперь я понимаю, что вы имеете в виду; Я не понимал, что вы имели в виду последнюю часть моего ответа. Когда тело имеет поле, его ограничительная рамка будет смещена на это количество пикселей на каждой соответствующей стороне. В этом случае вам также придется вычесть вычисленный стиль поля из координат тела. Стоит отметить, что сброс CSS приводит к удалению поля из <body>.
Andy E 4.07.2014 15:14:10
element.getBoundingClientRect().topне возвращает правильное верхнее смещение в случае position: fixedэлемента в iOS (iPhone 8), если он содержит сфокусированный элемент ввода и виртуальная клавиатура сдвинулась вверх. Например, если фактическое смещение от вершины окна составляет 200 пикселей, оно сообщит об этом как 420 пикселей, где 220 пикселей - высота виртуальной клавиатуры. Если вы установите элемент position: absoluteи разместите его в том же положении, как если бы он был зафиксирован, тогда вы получите правильные 200px. Я не знаю решения этого.
Jānis Elmeris 2.05.2018 17:58:30

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

<script>
  var el = $("#element");
  var position = el.position();
  console.log( "left: " + position.left + ", top: " + position.top );
</script>
8
16.04.2013 04:56:33

Чтобы получить позицию относительно страницы эффективно и без использования рекурсивной функции: (также включает 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;
23
10.08.2013 16:03:06
Включение всех важных scrollTop / scrollLeft делает этот ответ немного более правильным.
scunliffe 6.12.2014 22:24:38

Просто подумал, что я тоже это выброшу.
Я не смог протестировать его в старых браузерах, но он работает в последней версии топ-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()};
};
1
2.09.2015 13:08:09

Я успешно использовал решение Энди Э. для позиционирования модуса начальной загрузки 2 в зависимости от того, на какую ссылку в строке таблицы нажимает пользователь. Страница представляет собой страницу «Гобелен 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>

Ссылка в цикле:

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

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

2
23.10.2014 15:02:06
Этот js-код помог мне, у меня есть старое приложение webforms, использующее множественные заполнители для вставки страниц .aspx, и я не мог понять, как добавить appendChild () из всплывающего окна, которое я создавал, чтобы получить его в окне просмотра, потому что все дерево DOM не работает с несколькими заполнителями и неправильной разметкой. Использование body.getBoundingClientRect (), а затем использование его вершины в позиционировании было тем, что мне было нужно. Спасибо.
Brad Martin 14.08.2015 21:32:45

Самый чистый подход, который я нашел, - это упрощенная версия техники, используемой 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;

7
4.11.2014 14:37:47

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

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

Для восстановления левой позиции вы должны вернуть:

    return offsetRect.left - rootRect.left;
0
5.03.2015 15:07:40

Это сработало для меня (модифицировано из ответов с наибольшим количеством голосов)

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

Используя это мы можем позвонить

getOffset(element).left

или

getOffset(element).top
234
9.08.2018 18:12:47
Только это решение работает для меня, когда элемент помещен в divцентр с использованием css top:50%, left:50%; transform:translate(-50%, -50%);... отлично. Согласитесь с вопросом @ScottBiggs. Логично стремиться к простоте.
nelek 3.09.2015 20:57:42
может быть, это не победитель, потому что он такой же, как решение Энди Е., но не работает в старых браузерах <IE9
niltoid 10.06.2016 21:36:20
getBoundingClientRect вызывает огромный всплеск перерисовки в моих графиках производительности
frumbert 22.11.2017 04:14:52
Вы должны определить , rectиспользуя var, letили const. В противном случае он определяется как window.rect.
hev1 8.08.2018 01:44:13
left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)вернет среднее положение элемента
abhishake 5.04.2019 10:35:45

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

// 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

5
6.04.2015 21:21:34

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

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

1
18.06.2015 07:24:46

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

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

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

getAbsoluteOffsetFromRelative - возвращает абсолютную позицию относительно первого родительского элемента с position :lative. Это похоже на 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, который должен работать, если браузеры ведут себя , но не проверял остальное вообще.

10
1.12.2015 11:42:09
Интересно ... но в Edge getAbsoluteOffsetFromBody (element) .top возвращает другое значение при прокрутке, в Chrome оно остается неизменным при прокрутке. Кажется, Edge корректируется с помощью положения прокрутки. Когда элемент прокручивается из поля зрения, я получаю отрицательное значение.
Norman 13.01.2018 16:13:54
getAbsoluteOffsetFromRelative сделал мой день, я должен был воспроизвести всплывающую подсказку без Javascript начальной загрузки, это мне очень помогло.
Nolyurn 13.08.2018 15:52:58
На всякий случай, если Meouw изменит свое имя пользователя, ссылка на ответ: stackoverflow.com/a/442474/3654837 . (Я не хочу поднимать эту старую
Mukyuu 10.01.2020 07:22:42

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

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

8
25.08.2016 15:53:52
К сожалению, это не работает для всех элементов, которые можно найти в современном HTML-документе. Встроенные <svg>элементы, например, не имеют offsetLeft, offsetTopи offsetParentсвойства.
Jonathan Eunice 19.10.2016 09:39:29
Просто DIVили IMGнет SVG. Посмотреть "Посмотреть пример координат"? Вы можете найти объект svg в позиции вызова getOffsetRect , попробуйте и зависит от работы объекта.
KingRider 19.10.2016 20:24:17

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

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');
19
29.12.2017 10:27:30

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

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

Решение
Решение для меня было использование

window.visualViewport.pageTop

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

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


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

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

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

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

6
15.06.2018 18:27:59
это очень вероятно, чтобы быть в верхней части так много ответов, когда вы нажимаете активный, чтобы отсортировать ответы
lucchi 1.06.2018 11:48:42
@lucchi: D хорошо, я полагаю, я мог бы удалить текст @ сверху ... хотя я только что повторил этот вопрос и понял, что нашел лучшее решение для своей проблемы ... хотя мой ответ скорее обратите внимание на более полные ответы. Я подозреваю, что мои требования были не настолько распространены, чтобы другие ответы не работали для меня?
MER 1.06.2018 20:14:41
В любом случае, я ценю ваш ответ, просто хочу сказать, что любой желающий будет знать, что вы написали что-то новое. Вы не одиноки ....
lucchi 1.06.2018 22:22:56

Получить положение div относительно слева и сверху

  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 
-1
27.05.2018 02:11:45
Я проголосовал вниз, потому что нижний и правый не являются свойствами offset ()
MacroMan 8.05.2018 14:39:01
@MacroMan, я уважаю ваше решение, но я уже объяснил в тексте, что «нижний и правый код не проверен». Кроме того, я обновлю свой код очень скоро.
Vishal 8.05.2018 16:56:00
Я думаю, что el.offsetTopи el.offsetLeft(ОП ничего не говорит о jQuery ... Я не уверен, почему ваш ответ также использует jQuery ...)
mesqueeb 10.07.2018 06:57:44

Если вы хотите, чтобы это было сделано только в JavaScript , вот некоторые из них, используяgetBoundingClientRect()

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

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

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

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

getBoundingClientRect() является функцией javascript, которая возвращает позицию элемента относительно окна просмотра окна.

82
18.09.2019 17:50:47
Это должно быть решением. Здесь нет длинного кода bs, он понятен и очень точен!
E Alexis MT 21.09.2019 01:07:16
Что делать, если элемент находится внутри прокручиваемого элемента? Единственный способ сделать это - суммировать offsetTop всех родительских элементов, как предлагают другие ответы
Dmitri 8.11.2019 11:11:13
Как утверждает Дмитрий, это неправильно и очень некорректно. Он не должен иметь столько голосов, сколько имеет. Он также ВСЕГДА будет находиться в элементе с возможностью прокрутки, потому что сам документ можно прокручивать. Другими словами, если весь документ не помещается в области просмотра, он всегда будет неверным, если пользователь вообще прокрутил главное окно.
Lev 19.01.2020 20:11:31

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

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

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

el.offsetTop + getParentOffsets(el);
2
1.03.2019 13:56:36
/**
 *
 * @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 за ответ , это всего лишь другая версия.

2
29.08.2019 04:10:50