Wie erhalte ich die oberste Position eines Elements relativ zum Ansichtsfenster des Browsers?


173

Ich möchte die Position eines Elements relativ zum Ansichtsfenster des Browsers ermitteln (das Ansichtsfenster, in dem die Seite angezeigt wird, nicht die gesamte Seite). Wie geht das in JavaScript?

Danke vielmals


2
Ich denke, diese Frage ähnelt der von stackoverflow.com/questions/211703/…, die eine wirklich gute Lösung bietet.
Jakob Runge

1
@JakobRunge, das war 2013 "schön"?
Iulian Onofrei

1
Erwägen Sie, eine Lösung zu akzeptieren.
Iulian Onofrei

Antworten:


305

Die vorhandenen Antworten sind jetzt veraltet. Die native getBoundingClientRect()Methode gibt es schon eine ganze Weile und macht genau das, was die Frage verlangt. Außerdem wird es in allen Browsern unterstützt (einschließlich IE 5, wie es scheint!).

Von der MDN-Seite :

Der zurückgegebene Wert ist ein TextRectangle-Objekt, das schreibgeschützte Eigenschaften für links, oben, rechts und unten enthält, die das Rahmenfeld in Pixel beschreiben, wobei sich das obere linke relativ zum oberen linken Rand des Ansichtsfensters befindet .

Du benutzt es so:

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

3
Dies funktioniert möglicherweise nicht richtig, wenn Sie den Browser-Zoom (Android Chrome) verwenden. Lösung von @rism ( siehe unten ) funktioniert in diesem Fall
Dmitry

4
Gut für die meisten Fälle, aber es wird davon ausgegangen, dass sich das Element nicht in einem eingebetteten Iframe befindet, oder? Die Frage bezieht sich auf das Fenster des Browsers. Das el.getBoundingClientRect () gibt relativ das Fenster des Iframes zurück, nicht das Browserfenster.
Cakidnyc

6
Die Frage bezieht sich auf das Fenster des Browsers.
Dmitry Dvornikov

2
@Denilson getBoundingClientRect().topist nicht in meinem IE11, es gibt 0 zurück. Haben Sie eine Lösung.
Arif

@Arif: Entschuldigung, aber ich kann Ihr Problem nicht reproduzieren. Ich habe dies auf IE11 getestet und immer noch Ergebnisse erhalten: codepen.io/denilsonsa/pen/ypqyXj
Denilson Sá Maia

57

In meinem Fall habe ich, um beim Scrollen sicher zu sein, die window.scroll zur Gleichung hinzugefügt:

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

Dadurch kann ich die tatsächliche relative Position des Elements im Dokument ermitteln, auch wenn es gescrollt wurde.


2
Solltest du nicht die Bildlaufposition hinzufügen, anstatt sie zu subtrahieren?
Iulian Onofrei

Ich habe die Antwort positiv bewertet, aber trotzdem hat @lulian Onofrei recht. Bitte bearbeiten.
pmrotule

@Fabio getBoundingClientRect().topist nicht in meinem IE11, es gibt 0 zurück. Haben Sie eine Lösung.
Arif

1
@Arif window.scrollY || window.pageYOffsetkann die Unterstützung verbessern
Fabian von Ellerts

@ FabianvonEllerts :)
Arif

15

Bearbeiten: Fügen Sie Code hinzu, um das Scrollen der Seite zu berücksichtigen.

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

Das Argument id ist die ID des Elements, dessen Versatz Sie möchten. Adaptiert von einem Quirksmode-Beitrag .


1
Vielen Dank für Ihre Antwort, aber ich glaube, Sie haben meine Frage falsch verstanden. Ich weiß, wie man den Anfang eines Elements relativ zur Seite erhält. Ich versuche, die Position relativ zum 'Ansichtsfenster' (dh zum Browserfenster) zu ermitteln , nicht das Dokument)
Waleed Eissa

Entschuldigung, Ihre Verwendung des Ansichtsfensters hat mich umgehauen. Sie sagen also, Sie möchten das Chrome des Browsers berücksichtigen, dh die Lesezeichen-Symbolleiste, die Positionsleiste usw.?
Derek Swingley

Nein, nur das Fenster, durch das Sie die Seite sehen. Wenn die Seite gescrollt wird, unterscheidet sich diese von der Dokumentoberseite, andernfalls sind sie gleich.
Waleed Eissa

Oh ok ich verstehe. Ich bin mir nicht sicher, wie ich das machen soll ... wird meine Antwort bearbeiten, wenn mir etwas einfällt.
Derek Swingley

Ich habe den Code oben etwas hässlicher gemacht, aber es funktioniert ... benutze offsetParent.scrollTop
Derek Swingley

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

Dies scheint vom oberen Rand des Dokuments zu berechnen, nicht vom Ansichtsfenster
Scott Leonard

6

Du kannst es versuchen:

node.offsetTop - window.scrollY

Es funktioniert unter Opera mit definiertem Viewport-Meta-Tag.


7
Wenn ich die Dokumentation richtig verstehe , offsetTopbezieht sie sich auf das am nächsten positionierte Element. Was je nach Seitenstruktur ein Stammelement sein kann oder nicht.
Denilson Sá Maia

5

jQuery setzt dies recht elegant um. Wenn Sie sich die Quelle für jQuery's ansehen offset, werden Sie feststellen, dass dies im Grunde so implementiert ist:

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

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

2

Die Funktion auf dieser Seite gibt ein Rechteck mit den Koordinaten oben, links, Höhe und Breite eines übergebenen Elements relativ zum Browser-Ansichtsport zurück.

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

Quelle


1

Danke für alle Antworten. Es scheint, dass Prototype bereits eine Funktion hat, die dies ausführt (die Funktion page ()). Beim Anzeigen des Quellcodes der Funktion stellte ich fest, dass zuerst die Elementversatzposition relativ zur Seite (dh zur Dokumentoberseite) berechnet und dann das scrollTop davon subtrahiert wird. Weitere Informationen finden Sie im Quellcode des Prototyps.


Gute Entscheidung. Es ist wahrscheinlich am besten, mit einer der Hauptbibliotheken zu arbeiten, da diese mit größerer Wahrscheinlichkeit über alle Browser hinweg das gleiche Ergebnis liefern. Wenn Sie neugierig sind, überprüfen Sie meine meine Antwort. Der Code dort wird dies tun, aber ich habe keine Ahnung, wie er sich über alle Browser hinweg halten wird.
Derek Swingley

1

Ich gehe davon aus, dass ein Element mit der ID von btn1auf der Webseite vorhanden ist und dass jQuery enthalten ist. Dies hat in allen modernen Browsern von Chrome, FireFox, IE> = 9 und Edge funktioniert. jQuery wird nur verwendet, um die Position relativ zum Dokument zu bestimmen.

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 ist JavaScript. Ich glaube, Sie meinten "es ist nicht 100% Vanille / reines JS."
Hungerstar

Ja das meinte ich.
Sunil

1

Manchmal getBoundingClientRect()zeigt der Eigenschaftswert des Objekts 0 für IE. In diesem Fall müssen Sie display = 'block'für das Element festlegen . Sie können den folgenden Code für alle Browser verwenden, um den Offset zu erhalten.

Erweitern Sie die jQuery-Funktionalität:

(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));

Verwenden :

var elementOffset = $("#" + elementId).weOffset();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.