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

Я хочу знать, как получить X и Y позицию HTML-элементов, таких как img и div в JavaScript.

853
14 янв. '09 в 12:35
источник поделиться
22 ответов

Правильный подход заключается в использовании 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>');
1095
09 июля '12 в 17:06
источник

Связанные вопросы


Похожие вопросы

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

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; 
238
14 янв. '09 в 13:04
источник

Это сработало для меня (изменено с самого высокого проголосовавшего ответа):

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

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

getOffset(element).left

или

getOffset(element).top
102
29 янв. '15 в 21:46
источник

Если страница включает в себя - по крайней мере, любую "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];
};

28
12 авг. '10 в 23:14
источник

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

26
14 янв. '12 в 11:57
источник

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

var element = document.getElementById('elementId'); //replace elementId with your element 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;
20
26 июля '13 в 4:49
источник

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

offsetLeft
offsetTop

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

IE и FF3 имеют

clientLeft
clientTop

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

18
14 янв. '09 в 12:43
источник

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

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

15
14 янв. '09 в 12:47
источник

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

13
18 авг. '10 в 17:43
источник

Как о чем-то подобном, передавая идентификатор элемента, и он вернет левый или верхний, мы можем их объединить:

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');
11
22 мая '17 в 16:09
источник

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

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

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

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

7
01 дек. '15 в 10:24
источник

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

например.

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

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

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

7
14 янв. '09 в 13:24
источник

Это лучший код, который мне удалось создать (работает и в iframe, в отличие от jQuery offset()). Кажется, у 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 };
}
6
10 сент. '11 в 20:05
источник

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

<script>
  var el = $("#element");
  var position = el.position();
  console.log( "left: " + position.left + ", top: " + position.top );
</script>
6
16 апр. '13 в 7:56
источник

Самый чистый подход, который я нашел, - это упрощенная версия метода, используемого jQuery offset. Подобно некоторым другим ответам, он начинается с getBoundingClientRect; он затем использует window и documentElement для настройки положения прокрутки, а также таких вещей, как margin на 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>
4
04 нояб. '14 в 17:17
источник

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

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

4
25 авг. '16 в 18:44
источник

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

// For really old browser 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

3
15 марта '15 в 15:11
источник

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

Я успешно использовал решение Andy E для размещения бутстрапа 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>

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

<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 окт. '14 в 18:02
источник

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

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
17 июня '15 в 23:48
источник

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

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

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

    return offsetRect.left - rootRect.left;
0
08 янв. '15 в 20:42
источник

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

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

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

window.visualViewport.pageTop

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

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

0
24 окт. '17 в 22:23
источник

Посмотрите другие вопросы по меткам или Задайте вопрос