Obter a posição (X, Y)de um elemento HTML em relação à janela do navegador

quero saber como obter a posição X e Y dos elementos HTML como img e div em JavaScript em relação à janela do navegador.

Author: Jack, 2009-01-14

27 answers

A abordagem correcta é usar element.getBoundingClientRect():

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

Internet Explorer tem suportado isso desde que você é susceptível de se importar com e foi finalmente padronizado em CSSOM Views . Todos os outros navegadores o adoptaram há muito tempo.

Alguns navegadores também devolvem propriedades de altura e largura, embora isto não seja normal. Se você está preocupado com a compatibilidade do navegador mais antigo, verifique as revisões desta resposta para um degradante otimizado implementacao.

Os valores devolvidos por element.getBoundingClientRect() são relativos à área de visualização. Se precisar dele em relação a outro elemento, basta subtrair um rectângulo do outro:

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

alert('Element is ' + offset + ' vertical pixels from <body>');
 1968
Author: Andy E, 2018-01-10 13:44:57
As bibliotecas esforçam-se para obter compensações precisas para um elemento.
aqui está uma função simples que faz o trabalho em todas as circunstâncias que eu tentei.
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; 
 338
Author: meouw, 2015-09-27 01:42:32

Esta função devolve a posição de um elemento em relação ao documento inteiro (Página):

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

Usando isto podemos obter a posição X:

getOffset(element).left

... ou a posição Y:

getOffset(element).top
 274
Author: Adam Grant, 2020-12-03 08:46:09

Se você quiser que seja feito apenas em javascript , Aqui estão alguns one liners usando getBoundingClientRect()

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

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

A primeira linha irá voltar offsetTop dizer Y em relação ao documento. A segunda linha irá retornar offsetLeft diga X em relação ao documento.

getBoundingClientRect() é uma função javascript que retorna a posição do elemento em relação à visualização da janela.

 137
Author: Mustkeem K, 2020-04-29 09:40:21

Os elementos HTML na maioria dos navegadores terão: -

offsetLeft
offsetTop

Estes especificam a posição do elemento em relação ao seu parente mais próximo que tem layout. Este pai pode muitas vezes ser acessado bif a propriedade offsetParent.

IE e FF3 têm

clientLeft
clientTop

Estas propriedades são menos comuns, especificam uma posição de elementos com a sua área de clientes pais (área acolchoada é parte da área de clientes, mas fronteira e Margem não é).

 48
Author: AnthonyWJones, 2009-01-14 09:43:14

Se a página incluir-pelo menos-qualquer "DIV", a função dada por meouw lança o valor "Y" para além dos limites actuais da página. A fim de encontrar a posição exata, você precisa lidar com ambos os offset e parentNode.

Tente o código abaixo (está verificado para 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];
};

 36
Author: Refik Ayata, 2018-08-07 21:58:29

Pode adicionar duas propriedades a Element.prototype para obter a parte superior/esquerda de qualquer elemento.

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 );
    }
} );
Isto chama-se assim:
var x = document.getElementById( 'myDiv' ).documentOffsetLeft;
Aqui está uma demonstração comparando os resultados com os do jQuery..left: http://jsfiddle.net/ThinkingStiff/3G7EZ/
 35
Author: ThinkingStiff, 2017-02-23 23:31:55

Para obter a posição relativa à página de forma eficiente, e sem usar uma função recursiva: (inclui IE também)

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;
 25
Author: Abdul Rahim Haddad, 2013-08-10 16:03:06

Que tal algo como isto, passando o ID do elemento e ele irá devolver o esquerdo ou o topo, também podemos combiná-los:

1) procurar à esquerda

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

2) procurar o topo

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

Ou 3) Encontrar a esquerda e o topo juntos

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');
 20
Author: Alireza, 2017-12-29 10:27:30

Você pode ser melhor servido usando um framework JavaScript, que tem funções para retornar tais informações (e muito mais!) in a browser-independant fashion. Aqui estão alguns:

Com estes quadros, podias fazer algo como: $('id-of-img').top para obter a coordenada y-pixel da imagem.
 16
Author: Shalom Craimer, 2010-12-09 07:56:38

JQuery .offset () irá obter as coordenadas actuais do primeiro elemento, ou definir as coordenadas de cada elemento, no conjunto de elementos correspondentes, em relação ao documento.

 16
Author: akauppi, 2017-02-24 00:49:49

Eu peguei a resposta de @meouw, adicionada no clientLeft que permite a fronteira, e então criei três versões:

GetAbsoluteOffsetFromBody - semelhante ao @meouw, este obtém a posição absoluta em relação ao corpo ou elemento html do documento (dependendo do quirks mode)

GetAbsoluteOffsetFromGivenElement-devolve a posição absoluta em relação ao elemento indicado (relativeEl). Note que o elemento indicado deve conter o elemento el, ou Isto irá comportar o o mesmo que conseguir uma solução de todos. Isto é útil se você tiver dois elementos contidos dentro de outro elemento (conhecido) (opcionalmente vários nós acima da árvore de nós) e quiser torná-los a mesma posição.

GetAbsoluteOffsetFromRelative-devolve a posição absoluta em relação ao primeiro elemento-mãe com a posição: relativa. Isto é semelhante a getAbsoluteOffsetFromGivenElement, pela mesma razão, mas só vai tão longe quanto o primeiro elemento correspondente.

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

Se estiver ainda tendo problemas, particularmente relacionados com a rolagem, você poderia tentar olhar para http://www.greywyvern.com/?post=331 notei pelo menos um pedaço de código questionável em getStyle, o que seria bom se os navegadores se comportassem, mas não testaram o resto.

 10
Author: James Carlyle-Clarke, 2015-12-01 11:42:09
/**
 *
 * @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;
}

Thank ThinkingStiff for the answer , this is only another version.

 9
Author: Văn Quyết, 2020-10-12 02:45:52

Se usar o jQuery, o plugin de dimensões é excelente e permite-lhe indicar exactamente o que deseja.

Por exemplo

Posição relativa, posição absoluta, posição absoluta sem enchimento, com enchimento...

Continua, digamos que há muito que podes fazer com ele.

Além do bónus de usar o jQuery é o tamanho de ficheiro leve e fácil de usar, não vai voltar ao JavaScript sem ele depois.

 8
Author: John_, 2011-07-14 21:37:31

Se estiver a utilizar jQuery, esta pode ser uma solução simples:

<script>
  var el = $("#element");
  var position = el.position();
  console.log( "left: " + position.left + ", top: " + position.top );
</script>
 8
Author: Adam Boostani, 2013-04-16 04:56:33

Diferença entre pequeno e pequeno

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

Veja um exemplo de coordenadas: http://javascript.info/tutorial/coordinates

 8
Author: KingRider, 2016-08-25 15:53:52

A abordagem mais limpa que encontrei é uma versão simplificada da técnica usada pela jQuery offset. Semelhante a algumas das outras respostas que começa com getBoundingClientRect; Ele então usa o window e o documentElement para ajustar para posição de deslocamento, bem como coisas como a margem no body (geralmente o padrão).

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>
 7
Author: James Montagne, 2014-11-04 14:37:47

Este é o melhor código que consegui criar (funciona também no iframes, ao contrário do offset do jQuery ()). Parece que o webkit tem um comportamento diferente.

Baseado no Comentário de 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
Author: Ron Reiter, 2011-09-10 17:05:08
Embora seja muito provável que isto se perca no fundo de tantas respostas, as soluções de topo aqui não funcionavam para mim.
Tanto quanto sei, nenhuma das outras respostas teria ajudado.

Situação:
Em uma página HTML5 eu tinha um menu que era um elemento nav dentro de um cabeçalho (não o cabeçalho, mas um cabeçalho em outro elemento).
Eu queria que a navegação para ficar no topo uma vez que um usuário girou para ele, mas antes disso o cabeçalho foi posicionado absoluto (para que pudesse sobrepor-se a outra coisa ligeiramente).
As soluções acima nunca desencadearam uma mudança porque .offettop não iria mudar, pois este era um elemento posicionado absoluto. Além disso, o .a propriedade scrollTop era simplesmente o topo do elemento mais alto... ou seja, 0 e sempre seria 0.
Quaisquer testes que eu realizei utilizando estes dois (e o mesmo com resultados getBoundingClientRect) não me diria se o topo da barra de navegação alguma vez deslizou para o topo do visualizável page (novamente, como relatado no console, eles simplesmente permaneceram os mesmos números enquanto rolagem ocorreu).

Solução
A solução para mim era utilizar

window.visualViewport.pageTop

O valor da propriedade pageTop reflecte a secção visualizável do ecrã, permitindo-me, portanto, localizar onde um elemento está em referência aos limites da área visualizável.

Provavelmente não é necessário dizer, sempre que estou a lidar com a rolagem espero usar esta solução para responder programaticamente ao movimento dos elementos que estão sendo patrulhados. Espero que ajude outra pessoa.
nota importante: isto parece funcionar no Chrome e no Opera actualmente e definitivamente não no Firefox (6-2018)... até o Firefox suportar visualisewport eu recomendo não usar este método, (e espero que eles o façam em breve... faz muito mais sentido do que o resto).


actualização:
Apenas uma nota sobre esta solução. Enquanto ainda encontro o que descobri ser muito valioso para situações em que"...programaticamente responder ao movimento de elementos sendo patrulhados."é aplicável. A melhor solução para o problema que eu tinha era usar CSS para definir posição: sticky no elemento. Usando o sticky você pode ter um elemento ficar no topo sem usar o javascript (Nota: Há momentos em que isso não vai funcionar tão eficazmente como mudar o elemento para fixo, mas para a maioria dos usos a abordagem sticky provavelmente será superior)

UPDATE01:
Então eu percebi que para uma página diferente eu tinha um requisito onde eu precisava detectar a posição de um elemento em uma configuração de rolagem ligeiramente complexa (parallax mais elementos que passam como parte de uma mensagem). Percebi nesse cenário que o seguinte forneceu o valor que utilizei para determinar quando fazer algo:
  let bodyElement = document.getElementsByTagName('body')[0];
  let elementToTrack = bodyElement.querySelector('.trackme');
  trackedObjPos = elementToTrack.getBoundingClientRect().top;
  if(trackedObjPos > 264)
  {
    bodyElement.style.cssText = '';
  }
Espero que esta resposta seja mais útil agora.
 6
Author: MER, 2018-06-15 18:27:59
Fiz assim, por isso era compatível com navegadores antigos.
// 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;
    }

Mais sobre as coordenadas em JavaScript aqui: http://javascript.info/tutorial/coordinates

 5
Author: Bojan Kseneman, 2015-04-06 21:21:34

Para obter o deslocamento total de um elemento, você pode resumir recursivamente todas as compensações-mãe:

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

Com esta função de utilidade, o deslocamento total de topo de um elemento dom é:

el.offsetTop + getParentOffsets(el);
 4
Author: Kevin K., 2019-03-01 13:56:36

Usei com sucesso a solução do Andy E para posicionar um modal bootstrap 2, dependendo do link numa linha de tabela em que o utilizador clica. A página é uma tapeçaria de 5 páginas e javascript abaixo é importado na classe java page.

Javascript:

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

}

O meu código modal:

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

A ligação no laço:

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

E o código java na classe page:

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');");
        }
    });
}
Espero que isto ajude alguém, este post ajudou.
 2
Author: Mark Espinoza, 2014-10-23 15:02:06

Depois de muita pesquisa e testes, isto parece funcionar

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

Ver http://jsbin.com/xuvovalifo/edit?html,js, saída

 1
Author: kernowcode, 2015-06-18 07:24:46
Pensei em deitar isto fora também.
Eu não fui capaz de testá-lo em navegadores mais antigos, mas ele funciona na última das três melhores. :)
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
Author: Duncan, 2015-09-02 13:08:09

Uma vez que os diferentes navegadores estão a fazer fronteira, estofamento, margem e etc de forma diferente. Eu escrevi uma pequena função para recuperar as posições superior e esquerda de um elemento específico em cada elemento raiz que você quer em dimensão precisa:

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

Para recuperar a posição esquerda deve regressar:

    return offsetRect.left - rootRect.left;
 0
Author: samadadi, 2015-03-05 15:07:40

Isto é tão fácil como duas linhas em JS:

var elem = document.getElementById("id");    
alert(elem.getBoundingClientRect());
 0
Author: Talha Rafique, 2020-08-12 12:18:35

Posicionar o div em relação à esquerda e ao topo

  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
Author: Vishal Kumar, 2018-05-27 02:11:45