Come ottenere la posizione più alta di un elemento rispetto alla vista del browser?


173

Voglio ottenere la posizione di un elemento rispetto alla finestra del browser (la finestra in cui viene visualizzata la pagina, non l'intera pagina). Come può essere fatto in JavaScript?

Grazie molto


2
Penso che questa domanda sia simile a stackoverflow.com/questions/211703/… che ha una soluzione davvero bella.
Jakob Runge,

1
@JakobRunge, è stato "bello" nel 2013?
Iulian Onofrei il

1
Prendi in considerazione l'idea di accettare una soluzione.
Iulian Onofrei il

Risposte:


306

Le risposte esistenti sono ora obsolete. Il getBoundingClientRect()metodo nativo esiste da un po 'di tempo ormai e fa esattamente quello che la domanda chiede. Inoltre è supportato su tutti i browser (incluso IE 5, a quanto pare!)

Dalla pagina MDN :

Il valore restituito è un oggetto TextRectangle, che contiene proprietà di sola lettura sinistra, superiore, destra e inferiore che descrivono il riquadro-bordo, in pixel, con la parte superiore sinistra rispetto alla parte superiore sinistra della finestra .

Lo usi così:

var viewportOffset = el.getBoundingClientRect();
// these are relative to the viewport, i.e. the window
var top = viewportOffset.top;
var left = viewportOffset.left;

3
Questo potrebbe non funzionare correttamente quando si utilizza lo zoom del browser (Android Chrome). La soluzione di @rism ( vedi sotto ) funziona in questo caso
Dmitry

4
Buono per la maggior parte dei casi, ma presuppone che l'elemento non si trovi all'interno di un iframe incorporato, giusto? La domanda è relativa alla finestra relativa del browser. El.getBoundingClientRect () restituirà la relativa finestra iframe, non la finestra del browser.
cakidnyc,

6
La domanda è relativa alla finestra relativa del browser.
Dmitry Dvornikov

2
@Denilson getBoundingClientRect().topnon è nel mio IE11 restituisce 0. Hai qualche soluzione.
Arif,

@Arif: mi dispiace, ma non riesco a riprodurre il tuo problema. Ho provato questo su IE11 e ho ancora ottenuto risultati: codepen.io/denilsonsa/pen/ypqyXj
Denilson Sá Maia

57

Nel mio caso, solo per sicurezza riguardo allo scorrimento, ho aggiunto il window.scroll all'equazione:

var element = document.getElementById('myElement');
var topPos = element.getBoundingClientRect().top + window.scrollY;
var leftPos = element.getBoundingClientRect().left + window.scrollX;

Ciò mi consente di ottenere la posizione relativa reale dell'elemento sul documento, anche se è stato fatto scorrere.


2
Non dovresti aggiungere la posizione di scorrimento invece di sottrarla?
Iulian Onofrei il

Ho votato a favore della risposta, ma ancora, @lulian Onofrei ha ragione. Per favore modifica.
pmrotule,

@Fabio getBoundingClientRect().topnon è nel mio IE11 restituisce 0. Hai qualche soluzione.
Arif,

1
@Arif window.scrollY || window.pageYOffsetpuò migliorare il supporto
Fabian von Ellerts

@FabianvonEllerts :)
Arif

15

Modifica: aggiungi un codice all'account per lo scorrimento della pagina.

function findPos(id) {
    var node = document.getElementById(id);     
    var curtop = 0;
    var curtopscroll = 0;
    if (node.offsetParent) {
        do {
            curtop += node.offsetTop;
            curtopscroll += node.offsetParent ? node.offsetParent.scrollTop : 0;
        } while (node = node.offsetParent);

        alert(curtop - curtopscroll);
    }
}

L'argomento id è l'id dell'elemento di cui si desidera l'offset. Adattato da un post in modalità quirks .


1
Grazie per la tua risposta, ma penso che tu abbia frainteso la mia domanda, so come ottenere la parte superiore di un elemento rispetto alla pagina, quello che sto cercando di fare è ottenere la posizione relativa al "viewport" (cioè la finestra del browser , non il documento)
Waleed Eissa,

Mi dispiace, il tuo uso di 'viewport' mi ha gettato. Quindi, stai dicendo che vuoi rendere conto del browser Chrome, ad esempio barra dei segnalibri, barra della posizione, ecc.?
Derek Swingley,

No, solo la finestra attraverso la quale vedi la pagina. Se si scorre la pagina, questa sarà diversa dalla parte superiore del documento, altrimenti saranno uguali.
Waleed Eissa,

Oh ok ho capito. Non sono sicuro di come farlo ... modificherò la mia risposta se trovo qualcosa.
Derek Swingley,

Ho reso il codice sopra un po 'più brutto ma funziona ... usa offsetParent.scrollTop
Derek Swingley

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

Questo sembra calcolare dalla cima del documento, non dal viewport
Scott Leonard,

6

Puoi provare:

node.offsetTop - window.scrollY

Funziona su Opera con il meta tag viewport definito.


7
Se capisco correttamente la documentazione , offsetTopè relativo all'elemento posizionato più vicino. Che, a seconda della struttura della pagina, può essere o meno un elemento radice.
Denilson Sá Maia,

5

jQuery lo implementa abbastanza elegantemente. Se guardi la fonte di jQuery offset, scoprirai che questo è fondamentalmente il modo in cui è implementato:

var rect = elem.getBoundingClientRect();
var win = elem.ownerDocument.defaultView;

return {
    top: rect.top + win.pageYOffset,
    left: rect.left + win.pageXOffset
};

2

La funzione in questa pagina restituirà un rettangolo con le coordinate superiore, sinistra, altezza e larghezza di un elemento passato rispetto alla porta di visualizzazione del browser.

    localToGlobal: function( _el ) {
       var target = _el,
       target_width = target.offsetWidth,
       target_height = target.offsetHeight,
       target_left = target.offsetLeft,
       target_top = target.offsetTop,
       gleft = 0,
       gtop = 0,
       rect = {};

       var moonwalk = function( _parent ) {
        if (!!_parent) {
            gleft += _parent.offsetLeft;
            gtop += _parent.offsetTop;
            moonwalk( _parent.offsetParent );
        } else {
            return rect = {
            top: target.offsetTop + gtop,
            left: target.offsetLeft + gleft,
            bottom: (target.offsetTop + gtop) + target_height,
            right: (target.offsetLeft + gleft) + target_width
            };
        }
    };
        moonwalk( target.offsetParent );
        return rect;
}

2
function inViewport(element) {
    let bounds = element.getBoundingClientRect();
    let viewWidth = document.documentElement.clientWidth;
    let viewHeight = document.documentElement.clientHeight;

    if (bounds['left'] < 0) return false;
    if (bounds['top'] < 0) return false;
    if (bounds['right'] > viewWidth) return false;
    if (bounds['bottom'] > viewHeight) return false;

    return true;
}

fonte


1

Grazie per tutte le risposte Sembra che Prototype abbia già una funzione che lo fa (la funzione page ()). Visualizzando il codice sorgente della funzione, ho scoperto che prima calcola la posizione di offset dell'elemento rispetto alla pagina (ovvero la parte superiore del documento), quindi sottrae lo scrollTop da quello. Vedi il codice sorgente del prototipo per maggiori dettagli.


Buona decisione. Probabilmente è meglio andare con una delle principali librerie poiché hanno maggiori probabilità di dare lo stesso risultato su tutti i browser. Se sei curioso, controlla la mia risposta. Il codice lì farà questo, ma non ho idea di come reggerà attraverso i browser.
Derek Swingley,

1

Sto supponendo che btn1nella pagina Web esista un elemento con un ID e che jQuery sia incluso. Questo ha funzionato su tutti i browser moderni di Chrome, FireFox, IE> = 9 e Edge. jQuery viene utilizzato solo per determinare la posizione relativa al documento.

var screenRelativeTop =  $("#btn1").offset().top - (window.scrollY || 
                                            window.pageYOffset || document.body.scrollTop);

var screenRelativeLeft =  $("#btn1").offset().left - (window.scrollX ||
                                           window.pageXOffset || document.body.scrollLeft);

1
jQuery è JavaScript. Credo che volevi dire "non è 100% vaniglia / JS puro".
Hungerstar,

Sì, questo è ciò che intendevo.
Sunil,

1

A volte getBoundingClientRect()il valore della proprietà dell'oggetto mostra 0 per IE. In tal caso, devi impostare display = 'block'l'elemento. È possibile utilizzare il codice seguente per tutti i browser per ottenere offset.

Estendi la funzionalità jQuery:

(function($) {
    jQuery.fn.weOffset = function () {
        var de = document.documentElement;
        $(this).css("display", "block");
        var box = $(this).get(0).getBoundingClientRect();
        var top = box.top + window.pageYOffset - de.clientTop;
        var left = box.left + window.pageXOffset - de.clientLeft;
        return { top: top, left: left };
    };
}(jQuery));

Uso :

var elementOffset = $("#" + elementId).weOffset();
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.