Trovare la posizione dell'elemento rispetto al documento


113

Qual è il modo più semplice per determinare la posizione di un elemento rispetto al documento / corpo / finestra del browser?

In questo momento sto usando .offsetLeft/offsetTop, ma questo metodo ti dà solo la posizione relativa all'elemento genitore, quindi devi determinare quanti genitori per l'elemento corpo, per conoscere la posizione relativa al corpo / finestra del browser / posizione del documento.

Questo metodo è anche ingombrante.

Risposte:


58

Puoi attraversare offsetParentfino al livello più alto del DOM.

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

28
No, non lo fa, quando qualsiasi genitore (specialmente l'elemento html !!!) ha margini, padding o bordi.
Flash Thunder

per quanto riguarda le cose sui margini ... potrebbe essere utile impostare il dimensionamento della scatola su border-box ... o qualcosa del genere ... niente che non possa essere risolto ...

Innanzitutto, è necessario decidere se tenere conto del bordo e del margine in base al dimensionamento della scatola. In secondo luogo, dovrebbe essere considerato il margine collassato. Infine, ci sarà una situazione più complicata in futuro che peggiorerebbe questa risposta.
xianshenglu

6
Perché questa è la risposta accettata? Questo è obsoleto e con scarse prestazioni. Fatti un favore e usa getBoundingClientRect () come suggerito nelle altre risposte.
Fabian von Ellerts

177

Puoi andare in alto e a sinistra senza attraversare DOM in questo modo:

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

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

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

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

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

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

6
Questa risposta non tiene conto degli offset dei genitori. È solo relativo al viewport
Nickey

3
@ Nickey non è vero: la posizione del riquadro di visualizzazione, più i controlli dell'offset di scorrimento, forniscono le coordinate relative all'intero documento.
natchiketa

1
Può essere soggetto a bug sui dispositivi mobili stackoverflow.com/a/32623832/962634 Bisogno di ricerca
basil

1
Perché sottrai clientTop / clientLeft?
Teemoh

1
@Teemoh clientTop / clientLeft corrisponde ai valori del bordo <html>sull'elemento.
Raphael Rafatpanah

98

È possibile utilizzare element.getBoundingClientRect()per recuperare la posizione dell'elemento rispetto alla finestra.

Quindi utilizzare document.documentElement.scrollTopper calcolare l'offset del viewport.

La somma dei due darà la posizione dell'elemento rispetto al documento:

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

10
Relativo al viewport non è lo stesso rispetto al documento. Se la pagina viene fatta scorrere un po 'verso il basso, la parte superiore relativa alla visualizzazione sarà un numero inferiore rispetto alla parte superiore relativa al documento.
MrVimes

14
inizia rispetto al viewport e aggiunge scrollY per ottenerlo relativo al documento.
Joaquin Cuenca Abela

2
document.documentElement.scrollTopnon funziona in Safari, usa window.scrollYinvece
Fabian von Ellerts

7

Suggerisco di usare

element.getBoundingClientRect()

come qui proposto invece del calcolo manuale dell'offset tramite offsetLeft , offsetTop e offsetParent . come qui proposto In alcune circostanze * l'attraversamento manuale produce risultati non validi. Vedi questo Plunker: http://plnkr.co/pC8Kgj

* Quando l'elemento è all'interno di un genitore scorrevole con posizionamento statico (= predefinito).


È possibile far funzionare il calcolo dell'offset anche incorporando scrollLeft e scrollTop in esso.
Ben J

Ma ho trovato offsetLefte offsetTopnon prendo in considerazione le trasformazioni CSS3, il che getBoundingClientRect()fa. Quindi questo è un caso in cui i risultati potrebbero non essere validi. Se ne hai bisogno, puoi ottenere l'offset di un elemento rispetto al genitore (simile offsetLeft) usando (element.getBoundingClientRect().left - parent.getBoundingClientRect().left).
Ben J

dovrebbe sicuramente salire più in alto; questi valori sono molto più utili e anche tutti in una chiamata!
mix3d

7

document-offset( Script di terze parti ) è interessante e sembra sfruttare gli approcci delle altre risposte qui.

Esempio:

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

5

Ho trovato il seguente metodo il più affidabile quando si tratta di casi limite che fanno scattare offsetTop / offsetLeft.

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

4

Per coloro che vogliono ottenere le coordinate xey di varie posizioni di un elemento, rispetto al documento.

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

uso

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

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

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


2

Se non ti dispiace usare jQuery, puoi usare offset()function. Fare riferimento alla documentazione se si desidera saperne di più su questa funzione.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.