Ich hatte diese 7 Codezeilen verwendet, die in allen Browsern mit Diskrepanzen in ie5,6,7 funktionieren (ich erinnerte mich nicht an ein Proboem ... könnte der Dokumenttyp sein) ... quirksmode.org/js/findpos. html und ich haben es seit so vielen Jahren oft benutzt. Vielleicht kann jemand auf die Fehler hinweisen, wenn überhaupt.
Jayapal Chandran
98
@AnthonyWJones, ich nehme an, Sie brauchten das pedantische Vergnügen, aber es ist offensichtlich, wie immer, wenn es nicht spezifiziert ist, dass sich das OP auf den allgemeinsten Fall oder auf die Fensterkoordinaten des Browsers bezieht.
Motes
7
@Mote, Nein, das ist nicht so offensichtlich. Lassen Sie Folgerungen, Subjektivität und falsche Axiome beiseite. Es kann relativ zum Ansichtsfenster oder zum Seitenanfang sein (auch bekannt als document.documentElement).
Andre Figueiredo
15
Die Standardeinstellung ist nicht die Folgerung, sondern die logische Folge, sodass sie relativ zum Fenster ist, oder "Seitenanfang" könnte der Begriff sein, wie Sie es ausdrücken. In der Spieltheorie wird es als ein Konzept kodifiziert, das als Schelling-Punkt bezeichnet wird. Stellen Sie sicher, dass Sie angeben, wann Sie nicht den allgemeinsten Fall meinen.
var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);
Internet Explorer hat dies unterstützt, solange Sie sich wahrscheinlich darum kümmern, und es wurde schließlich in CSSOM-Ansichten standardisiert . Alle anderen Browser haben es vor langer Zeit übernommen .
Einige Browser geben auch Eigenschaften für Höhe und Breite zurück, obwohl dies nicht dem Standard entspricht. Wenn Sie sich Sorgen über die Kompatibilität älterer Browser machen, überprüfen Sie die Revisionen dieser Antwort auf eine optimierte, sich verschlechternde Implementierung.
Die von zurückgegebenen Werte element.getBoundingClientRect()beziehen sich auf das Ansichtsfenster. Wenn Sie es relativ zu einem anderen Element benötigen, subtrahieren Sie einfach ein Rechteck vom anderen:
var bodyRect = document.body.getBoundingClientRect(),
elemRect = element.getBoundingClientRect(),
offset = elemRect.top - bodyRect.top;
alert('Element is '+ offset +' vertical pixels from <body>');
Funktioniert nicht ... es sind 8 Pixel vertikal und horizontal, aufgrund des 8px-Randes im Körper. Meouws Lösung funktioniert perfekt. Wenn Sie möchten, habe ich einen kleinen Test, um das Problem zu demonstrieren.
CpnCrunch
3
Eigentlich denke ich, es kommt darauf an, wovon du eigentlich die Koordinaten bekommen willst. Die Frage ist etwas mehrdeutig. Ihre Antwort ist richtig, wenn Sie nur die Koordinaten relativ zum Ansichtsfenster oder relativ zum Körperelement wollen, aber das hilft Ihnen nicht, wenn Sie die absolute Position des Elements wollen (was meiner Meinung nach die meisten Leute wollen). . Die Antwort von meouw gibt Ihnen das auch nicht, es sei denn, Sie entfernen die Bits '-scrollLeft' und '-scrollTop'.
CpnCrunch
4
@CpnCrunch: Ich verstehe, was du jetzt meinst; Ich wusste nicht, dass Sie sich auf den letzten Teil meiner Antwort beziehen. Wenn der Körper einen Rand hat, wird sein Begrenzungsrahmen auf jeder Seite um diese Anzahl von Pixeln versetzt. In diesem Fall müssten Sie auch den berechneten Randstil von den Körperkoordinaten subtrahieren. Es ist jedoch erwähnenswert, dass CSS-Resets den Rand entfernen <body>.
Andy E
3
element.getBoundingClientRect().topGibt bei einem position: fixedElement in iOS (iPhone 8) keinen korrekten oberen Versatz zurück, wenn es ein fokussiertes Eingabeelement enthält und die virtuelle Tastatur nach oben gerutscht ist. Wenn der tatsächliche Versatz von der Oberseite des Fensters beispielsweise 200 Pixel beträgt, wird er als 420 Pixel gemeldet, wobei 220 Pixel die Höhe der virtuellen Tastatur ist. Wenn Sie Elemente festlegen position: absoluteund an derselben Position wie fest positionieren, erhalten Sie die richtigen 200 Pixel. Ich kenne keine Lösung dafür.
Jānis Elmeris
327
Die Bibliotheken gehen einige Längen, um genaue Offsets für ein Element zu erhalten.
Hier ist eine einfache Funktion, die die Arbeit unter allen Umständen erledigt, die ich versucht habe.
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;
ändere: el = el.parentNode in: el = el.offsetParent; und es scheint jetzt für verschachtelte Iframes zu funktionieren ... Ich denke, das haben Sie beabsichtigt?
Adam
4
Diese Lösung ist unvollständig. Versuchen Sie, einen Div mit einem dicken Rand zu versehen und nisten Sie ihn einige Male. In jeder Version von Firefox (2-5) wird es um die Randbreite (n) versetzt (auch im Modus zur Einhaltung von Standards).
ck_
3
Gibt es dafür keinen saubereren Weg, wie eine el.totalOffsetLeft- und eine totalOffsetTop-Funktion? jQuery hat sicherlich diese Option, aber es ist eine Schande, dass es dafür keine offizielle Methode gibt. Müssen wir auf DOM4 warten? Ich erstelle eine HTML5-Canvas-Anwendung, daher denke ich, dass die beste Lösung darin besteht, Canvas-Elemente in einen Iframe einzufügen, damit ich echte Koordinaten mit clientX und clientY erhalten kann, wenn wir auf element klicken.
Taufe
1
Also, @Adam und meouw, sagen Sie, dass der erste Codeblock falsch ist? Warum dann nicht das ganz entfernen? (Diese Frage hat im Laufe der Jahre einige Zuschauer gesehen; könnte es schön sein, Dinge zu entfernen, wenn sie falsch sind?)
Arjan
2
@baptx: Ich weiß, dass dies eine späte Antwort ist, aber ich habe Ihren Kommentar nicht früher gesehen. In meiner Antwort unten finden Sie eine standardkonformere Alternative. Sie benötigen den Fallback-Code nicht einmal wirklich, da ihn die Browser seit langem unterstützen.
Andy E
242
Dies hat bei mir funktioniert (geändert von der Antwort mit der höchsten Stimme):
function getOffset(el){const rect = el.getBoundingClientRect();return{
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};}
Nur diese Lösung funktioniert für mich, wenn ein Element platziert wird, in divdessen Mitte CSS zentriert ist top:50%, left:50%; transform:translate(-50%, -50%);... ausgezeichnet. Stimmen Sie der @ ScottBiggs-Frage zu. Logisch ist es, nach Einfachheit zu suchen.
Nelek
3
Vielleicht ist es kein Gewinner, weil es das gleiche wie die Lösung von Andy E ist, aber es funktioniert nicht in alten Browsern <IE9
Niltoid
getBoundingClientRect verursacht einen massiven Repaint-Spike in meinen Performance-Charts
Frumbert
1
Sie sollten definieren rectverwenden var, letoder const. Ansonsten ist es definiert als window.rect.
Hev1
2
left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)wird die mittlere Position eines Elements zurückgeben
abhishake
97
Wenn Sie es nur in Javascript getan wollen , sind hier einige Einzeiler mitgetBoundingClientRect()
window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y
window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X
Die erste Zeile gibt offsetTopY relativ zum Dokument zurück. Die zweite Zeile gibt beispielsweise offsetLeftX relativ zum Dokument zurück.
getBoundingClientRect() ist eine Javascript-Funktion, die die Position des Elements relativ zum Ansichtsfenster des Fensters zurückgibt.
Dies sollte die Lösung sein. Es gibt hier keinen langen Code bs, es ist verständlich und sehr genau!
E Alexis MT
2
Was ist, wenn sich das Element in einem scrollbaren Element befindet? Die einzige Möglichkeit, dies zu tun, besteht darin, offsetTop aller übergeordneten Elemente zu summieren, wie andere Antworten vermuten lassen
Dmitri Pisarev,
Wie Dmitri feststellt, ist dies falsch und sehr fehlerhaft. Es sollte nicht so viele Stimmen haben wie es ist. Es befindet sich IMMER auch in einem scrollbaren Element, da das Dokument selbst gescrollt werden kann. Mit anderen Worten, es sei denn, das gesamte Dokument passt in das Ansichtsfenster, ist es immer falsch, wenn der Benutzer überhaupt durch das Hauptfenster gescrollt hat.
Lev
46
HTML-Elemente in den meisten Browsern haben: -
offsetLeft
offsetTop
Diese geben die Position des Elements relativ zu seinem nächsten übergeordneten Element mit Layout an. Auf dieses übergeordnete Element kann häufig über die Eigenschaft offsetParent zugegriffen werden.
IE und FF3 haben
clientLeft
clientTop
Diese Eigenschaften sind weniger verbreitet. Sie geben eine Elementposition mit dem übergeordneten Clientbereich an (der aufgefüllte Bereich ist Teil des Clientbereichs, Rand und Rand jedoch nicht).
Wenn die Seite mindestens "DIV" enthält, wirft die von meouw angegebene Funktion den Wert "Y" über die aktuellen Seitengrenzen hinaus. Um die genaue Position zu finden, müssen Sie sowohl offsetParent's als auch parentNode's verarbeiten.
Probieren Sie den folgenden Code aus (er ist auf FF2 geprüft):
Änderungen werden Element.prototypeim Allgemeinen als schlechte Idee angesehen . Es ist sehr schwierig, Code zu pflegen. Dieser Code berücksichtigt auch nicht das Scrollen.
Jared Forsyth
23
So rufen Sie die Position relativ zur Seite effizient und ohne Verwendung einer rekursiven Funktion ab: (einschließlich IE)
var element = document.getElementById('elementId');//replace elementId with your element's Id.var rect = element.getBoundingClientRect();var elementLeft,elementTop;//x and yvar 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;
Durch das Einfügen aller wichtigen scrollTop / scrollLeft wird diese Antwort etwas korrekter.
Scunliffe
19
Wie wäre es mit so etwas, indem wir die ID des Elements übergeben und es links oder oben zurückgibt, können wir sie auch kombinieren:
1) links finden
function findLeft(element){var rec = document.getElementById(element).getBoundingClientRect();return rec.left + window.scrollX;}//call it like findLeft('#header');
2) finde oben
function findTop(element){var rec = document.getElementById(element).getBoundingClientRect();return rec.top + window.scrollY;}//call it like findTop('#header');
oder 3) links und oben zusammen finden
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');
Möglicherweise ist es besser, ein JavaScript-Framework zu verwenden, das über Funktionen verfügt, mit denen solche Informationen (und vieles mehr!) Browserunabhängig zurückgegeben werden können. Hier sind ein paar:
@Costa Sie alle verwenden diese Art von Funktionen, obwohl dies ein sich entwickelndes Feld ist, da verschiedene Browser unterschiedlich der Spezifikation entsprechen. So viel im Code befasst sich mit dem "Reparieren" von Dingen, die schief gehen. Sie sollten sich wirklich den Quellcode ansehen.
Shalom Craimer
18
@scraimer: jQuery und YUI sind KEINE Frameworks !!! Das sind Bibliotheken ! Es ist nicht das gleiche. Unter Berufung auf jquery.com : "jQuery ist eine schnelle, kleine und funktionsreiche JavaScript- Bibliothek ." Unter Berufung auf yuilibrary.com (Sie können das "Zauberwort" auch in der URL sehen ...): "YUI ist eine kostenlose Open-Source-JavaScript- und CSS- Bibliothek zum Erstellen von interaktiven Webanwendungen."
Sk8erPeter
29
Sie sollten also nur für diese einfache Aufgabe riesige Bibliotheken verwenden? Nicht nötig. Ich hasse es, dass ich jedes Mal, wenn ich etwas mit js machen möchte, diese jQuery-Lösungen bekomme. jQuery ist nicht JS!
Opptatt Jobber
1
@OpptattJobber Ich stimme zu ... JQuery ist kein Javascript. Es basiert auf Javascript, ist aber eine ganz andere Programmiersprache.
Nick Manning
5
@NickManning Es ist keine neue Sprache, sondern eine Abstraktionsschicht für das DOM, bei der Kompatibilitäts- und Leistungsumgehungen nicht direkt in Ihren Code geschrieben werden müssen. Wenn Sie jQuery nicht verwenden, sollten Sie sowieso eine Art Abstraktionsschicht verwenden.
Ginman
15
jQuery .offset () ruft die aktuellen Koordinaten des ersten Elements ab oder legt die Koordinaten jedes Elements in der Gruppe der übereinstimmenden Elemente relativ zum Dokument fest.
Aus irgendeinem Grund werden im IE im Vergleich zu anderen Browsern nicht die gleichen Ergebnisse erzielt. Ich denke, dass es im IE eine Position relativ zum Fenster gibt. Wenn Sie also scrollen, erhalten Sie im IE andere Ergebnisse als in anderen
Ich habe die Antwort von @ meouw genommen, in der clientLeft hinzugefügt, die den Rand zulässt, und dann drei Versionen erstellt:
getAbsoluteOffsetFromBody - Ähnlich wie bei @ meouw wird hier die absolute Position relativ zum Hauptteil oder HTML-Element des Dokuments abgerufen (abhängig vom Mackenmodus).
getAbsoluteOffsetFromGivenElement - gibt die absolute Position relativ zum angegebenen Element (relativeEl) zurück. Beachten Sie, dass das angegebene Element das Element el enthalten muss. Andernfalls verhält es sich genauso wie getAbsoluteOffsetFromBody. Dies ist nützlich, wenn zwei Elemente in einem anderen (bekannten) Element enthalten sind (optional mehrere Knoten im Knotenbaum) und diese an derselben Position positionieren möchten.
getAbsoluteOffsetFromRelative - Gibt die absolute Position relativ zum ersten übergeordneten Element mit position: relative zurück. Dies ähnelt getAbsoluteOffsetFromGivenElement aus demselben Grund, geht jedoch nur bis zum ersten übereinstimmenden Element.
getAbsoluteOffsetFromBody =function( el ){// finds the offset of el from the body or html elementvar _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 relativeElvar _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: relativevar _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 };}
Wenn Sie immer noch Probleme haben, insbesondere beim Scrollen, können Sie sich http://www.greywyvern.com/?post=331 ansehen. Ich habe mindestens einen fragwürdigen Code in getStyle bemerkt, der in Ordnung sein sollte, vorausgesetzt, die Browser verhalten sich , aber den Rest habe ich überhaupt nicht getestet.
Interessant ... aber auf Edge gibt getAbsoluteOffsetFromBody (Element) .top beim Scrollen einen anderen Wert zurück, in Chrome bleibt er beim Scrollen konsistent. Es scheint, dass Edge sich mit der Bildlaufposition anpasst. Wenn das Element aus der Ansicht gescrollt wird, erhalte ich einen negativen Wert.
Norman
getAbsoluteOffsetFromRelative machte meinen Tag, ich musste Bootstrap-Tooltip ohne Javascript von Bootstrap reproduzieren, es hat mir sehr geholfen.
Nolyurn
Nur für den Fall, dass Meouw seinen Benutzernamen ändert, Link zur Antwort: stackoverflow.com/a/442474/3654837 . (Ich möchte diesen alten Thread nicht stoßen, also ja, ich habe einen Kommentar abgegeben)
Mukyuu
8
Wenn Sie jQuery verwenden, das Dimensions-Plugin hervorragend und ermöglicht es Ihnen, genau anzugeben, was Sie möchten.
z.B
Relative Position, absolute Position, absolute Position ohne Polsterung, mit Polsterung ...
Es geht weiter, sagen wir einfach, Sie können viel damit anfangen.
Der Vorteil der Verwendung von jQuery ist außerdem die geringe Dateigröße und die einfache Verwendung. Ohne jQuery können Sie danach nicht mehr auf JavaScript zurückgreifen.
Dies ist der beste Code, den ich erstellt habe (funktioniert auch in iframes, im Gegensatz zu jQuerys offset ()). Das Webkit scheint sich etwas anders zu verhalten.
Basierend auf meouws Kommentar:
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/safariif($.browser.webkit){
el = el.parentNode;}else{// firefox/IE
el = el.offsetParent;}}return{ top: _y, left: _x };}
Beachten Sie, dass Sie benötigen jQueryzu verwenden $.browser.webkit; Sie müssen herumspielen, um navigator.userAgentdasselbe mit pure zu tun JavaScript.
SP
2
$ .browser ist nicht mehr verfügbar in der neuesten Version von jQuery
Gus
Leider funktioniert der obige Code auch mit FF 24.4 nicht, wenn Randbreiten als Teil des Positionierungslayouts vorhanden sind.
Rob
8
Wenn Sie jQuery verwenden, kann dies eine einfache Lösung sein:
<script>var el = $("#element");var position = el.position();
console.log("left: "+ position.left +", top: "+ position.top );</script>
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 };}
Dies funktioniert leider nicht für alle Elemente, die in einem modernen HTML-Dokument enthalten sind. Embedded - <svg>Elemente, zum Beispiel, haben nicht offsetLeft, offsetTopund offsetParentEigenschaften.
Jonathan Eunice
Es ist gerecht DIVoder IMGnicht SVG. "Beispielkoordinaten anzeigen"? Sie können das Objekt svg als Positionsaufruf getOffsetRect finden. Versuchen Sie, die Objektarbeit abhängig zu machen.
KingRider
7
Der sauberste Ansatz, den ich gefunden habe, ist eine vereinfachte Version der von jQuery's verwendeten Technik offset. Ähnlich wie bei einigen anderen Antworten beginnt es mit getBoundingClientRect; Es verwendet dann das windowund das documentElement, um die Bildlaufposition sowie Dinge wie den Rand auf dem body(oft die Standardeinstellung) anzupassen .
Während dies bei so vielen Antworten sehr wahrscheinlich verloren geht, haben die Top-Lösungen hier bei mir nicht funktioniert.
Soweit ich das beurteilen konnte, hätte keine der anderen Antworten geholfen.
Situation :
Auf einer HTML5-Seite hatte ich ein Menü, das ein Navigationselement in einem Header war (nicht DER Header, sondern ein Header in einem anderen Element).
Ich wollte, dass die Navigation oben bleibt, sobald ein Benutzer zu ihr gescrollt hat, aber zuvor war die Kopfzeile absolut positioniert (damit ich sie etwas anderes leicht überlagern kann).
Die oben genannten Lösungen haben nie eine Änderung ausgelöst, da sich .offsetTop nicht ändern würde, da dies ein absolut positioniertes Element war. Zusätzlich war die .scrollTop-Eigenschaft einfach die Spitze des obersten Elements ... das heißt 0 und wäre immer 0.
Alle Tests, die ich mit diesen beiden durchgeführt habe (und die gleichen mit den Ergebnissen von getBoundingClientRect), haben mir nicht gesagt, ob der obere Rand der Navigationsleiste jemals zum oberen Rand der sichtbaren Seite gescrollt hat (wie in der Konsole angegeben, blieben sie beim Scrollen einfach die gleichen Zahlen aufgetreten).
Lösung
Die Lösung für mich war die Verwendung
window.visualViewport.pageTop
Der Wert der pageTop-Eigenschaft spiegelt den sichtbaren Bereich des Bildschirms wider, sodass ich verfolgen kann, wo sich ein Element in Bezug auf die Grenzen des sichtbaren Bereichs befindet.
Es ist wahrscheinlich unnötig zu sagen, dass ich diese Lösung jedes Mal verwenden werde, wenn ich mich mit dem Scrollen beschäftige, um programmgesteuert auf die Bewegung von Elementen zu reagieren, die gescrollt werden.
Hoffe es hilft jemand anderem.
WICHTIGER HINWEIS: Dies scheint derzeit in Chrome und Opera zu funktionieren und definitiv nicht in Firefox (6-2018) ... bis Firefox VisualViewport unterstützt. Ich empfehle, diese Methode NICHT zu verwenden (und ich hoffe, dass sie es bald tun ... es macht viel sinnvoller als der Rest).
UPDATE:
Nur ein Hinweis zu dieser Lösung. Während ich immer noch finde, dass das, was ich entdeckt habe, sehr wertvoll für Situationen ist, in denen "... programmgesteuert auf Bewegungen von Elementen reagiert wird, die gescrollt werden". anwendbar. Die bessere Lösung für das Problem, das ich hatte, war die Verwendung von CSS zum Einstellen Position: klebrigauf dem Element. Wenn Sie Sticky verwenden, kann ein Element ohne Verwendung von Javascript oben bleiben (
HINWEIS: Manchmal
funktioniert dies nicht so effektiv wie das Ändern des Elements in "Fixed", aber für die meisten Anwendungen ist der Sticky-Ansatz wahrscheinlich überlegen.)
UPDATE01:
Also habe ich das erkannt Für eine andere Seite hatte ich eine Anforderung, bei der ich die Position eines Elements in einem leicht komplexen Bildlauf-Setup ermitteln musste (Parallaxe plus Elemente, die als Teil einer Nachricht vorbeirollen). In diesem Szenario wurde mir klar, dass das Folgende den Wert lieferte, den ich verwendete, um zu bestimmen, wann etwas zu tun ist:
Dies ist sehr wahrscheinlich ganz oben auf so vielen Antworten, wenn Sie auf Aktiv klicken , um die Antworten zu sortieren
lucchi
@lucchi: D Nun, ich nehme an, ich könnte den Text @ oben entfernen ... obwohl ich gerade wieder in diesem Fall vorgekommen bin und festgestellt habe, dass ich eine bessere Lösung für mein eigenes Problem gefunden habe ... obwohl meine Antwort eher eine ist Fußnote zu den vollständigeren Antworten. Ich vermute, meine Anforderungen waren vielleicht nicht so häufig, dass die anderen Antworten bei mir nicht funktionierten?
MER
1
Ich schätze Ihre Antwort trotzdem, es war nur, um Ihnen zu sagen, dass jeder, der will, weiß, dass Sie etwas Neues geschrieben haben. Sie sind nicht allein ....
Lucchi
5
Ich habe es so gemacht, damit es mit alten Browsern kompatibel ist.
// For really old browser's or incompatible onesfunction getOffsetSum(elem){var top =0,
left =0,
bottom =0,
right =0var 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 browserreturn getOffsetSum(elem);}}elsereturnnull;}
Ich habe die Lösung von Andy E erfolgreich verwendet, um ein Bootstrap 2-Modal zu positionieren, je nachdem, auf welchen Link in einer Tabellenzeile ein Benutzer klickt. Die Seite ist eine Tapestry 5-Seite und das unten stehende Javascript wird in die Java-Seitenklasse importiert.
Dieser JS-Code hat mir geholfen. Ich habe eine alte Webforms-App mit mehreren Platzhaltern, in die ASPX-Seiten eingefügt wurden, und ich konnte nicht herausfinden, wie ichChild () eines Popup-Felds anhängen kann, das ich erstellt habe, um es in das Ansichtsfenster zu bringen, da der gesamte DOM-Baum fehlerhaft ist mit den mehreren Platzhaltern und falschem Markup. Die Verwendung von body.getBoundingClientRect () und die Verwendung der Oberseite bei der Positionierung war das, was ich brauchte. Vielen Dank.
Brad Martin
1
Nach vielen Recherchen und Tests scheint dies zu funktionieren
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 };}
Da verschiedene Browser Rahmen, Auffüllungen, Ränder usw. auf unterschiedliche Weise rendern. Ich habe eine kleine Funktion geschrieben, um die oberen und linken Positionen eines bestimmten Elements in jedem gewünschten Stammelement in einer genauen Dimension abzurufen:
Holen Sie sich die Position von div in Bezug auf links und oben
var elm = $('#div_id');//get the divvar posY_top = elm.offset().top;//get the position from topvar posX_left = elm.offset().left;//get the position from left
Ich habe nach unten gestimmt, weil unten und rechts keine Eigenschaften von offset () sind
MacroMan
@ MacroMan, ich respektiere Ihre Entscheidung, aber ich habe bereits im Text erklärt, dass "unten und rechts der Code nicht getestet wird". Außerdem werde ich meinen Code sehr bald aktualisieren.
Vishal
Ich denke, es ist el.offsetTopund el.offsetLeft(das OP sagt nichts über jQuery ... Ich bin nicht sicher, warum Ihre Antwort auch jQuery verwendet ...)
Antworten:
Der richtige Ansatz ist
element.getBoundingClientRect()
:Internet Explorer hat dies unterstützt, solange Sie sich wahrscheinlich darum kümmern, und es wurde schließlich in CSSOM-Ansichten standardisiert . Alle anderen Browser haben es vor langer Zeit übernommen .
Einige Browser geben auch Eigenschaften für Höhe und Breite zurück, obwohl dies nicht dem Standard entspricht. Wenn Sie sich Sorgen über die Kompatibilität älterer Browser machen, überprüfen Sie die Revisionen dieser Antwort auf eine optimierte, sich verschlechternde Implementierung.
Die von zurückgegebenen Werte
element.getBoundingClientRect()
beziehen sich auf das Ansichtsfenster. Wenn Sie es relativ zu einem anderen Element benötigen, subtrahieren Sie einfach ein Rechteck vom anderen:quelle
<body>
.element.getBoundingClientRect().top
Gibt bei einemposition: fixed
Element in iOS (iPhone 8) keinen korrekten oberen Versatz zurück, wenn es ein fokussiertes Eingabeelement enthält und die virtuelle Tastatur nach oben gerutscht ist. Wenn der tatsächliche Versatz von der Oberseite des Fensters beispielsweise 200 Pixel beträgt, wird er als 420 Pixel gemeldet, wobei 220 Pixel die Höhe der virtuellen Tastatur ist. Wenn Sie Elemente festlegenposition: absolute
und an derselben Position wie fest positionieren, erhalten Sie die richtigen 200 Pixel. Ich kenne keine Lösung dafür.Die Bibliotheken gehen einige Längen, um genaue Offsets für ein Element zu erhalten.
Hier ist eine einfache Funktion, die die Arbeit unter allen Umständen erledigt, die ich versucht habe.
quelle
Dies hat bei mir funktioniert (geändert von der Antwort mit der höchsten Stimme):
Damit können wir anrufen
oder
quelle
div
dessen Mitte CSS zentriert isttop:50%, left:50%; transform:translate(-50%, -50%);
... ausgezeichnet. Stimmen Sie der @ ScottBiggs-Frage zu. Logisch ist es, nach Einfachheit zu suchen.rect
verwendenvar
,let
oderconst
. Ansonsten ist es definiert alswindow.rect
.left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)
wird die mittlere Position eines Elements zurückgebenWenn Sie es nur in Javascript getan wollen , sind hier einige Einzeiler mit
getBoundingClientRect()
Die erste Zeile gibt
offsetTop
Y relativ zum Dokument zurück. Die zweite Zeile gibt beispielsweiseoffsetLeft
X relativ zum Dokument zurück.getBoundingClientRect()
ist eine Javascript-Funktion, die die Position des Elements relativ zum Ansichtsfenster des Fensters zurückgibt.quelle
HTML-Elemente in den meisten Browsern haben: -
Diese geben die Position des Elements relativ zu seinem nächsten übergeordneten Element mit Layout an. Auf dieses übergeordnete Element kann häufig über die Eigenschaft offsetParent zugegriffen werden.
IE und FF3 haben
Diese Eigenschaften sind weniger verbreitet. Sie geben eine Elementposition mit dem übergeordneten Clientbereich an (der aufgefüllte Bereich ist Teil des Clientbereichs, Rand und Rand jedoch nicht).
quelle
Wenn die Seite mindestens "DIV" enthält, wirft die von meouw angegebene Funktion den Wert "Y" über die aktuellen Seitengrenzen hinaus. Um die genaue Position zu finden, müssen Sie sowohl offsetParent's als auch parentNode's verarbeiten.
Probieren Sie den folgenden Code aus (er ist auf FF2 geprüft):
quelle
Sie können zwei Eigenschaften hinzufügen
Element.prototype
, um den oberen / linken Rand eines Elements abzurufen.Das nennt man so:
Hier ist eine Demo , die Ergebnisse zu jQuery zu vergleichen
offset().top
und.left
: http://jsfiddle.net/ThinkingStiff/3G7EZ/quelle
Element.prototype
im Allgemeinen als schlechte Idee angesehen . Es ist sehr schwierig, Code zu pflegen. Dieser Code berücksichtigt auch nicht das Scrollen.So rufen Sie die Position relativ zur Seite effizient und ohne Verwendung einer rekursiven Funktion ab: (einschließlich IE)
quelle
Wie wäre es mit so etwas, indem wir die ID des Elements übergeben und es links oder oben zurückgibt, können wir sie auch kombinieren:
1) links finden
2) finde oben
oder 3) links und oben zusammen finden
quelle
Möglicherweise ist es besser, ein JavaScript-Framework zu verwenden, das über Funktionen verfügt, mit denen solche Informationen (und vieles mehr!) Browserunabhängig zurückgegeben werden können. Hier sind ein paar:
Mit diesen Frameworks können Sie Folgendes tun:
$('id-of-img').top
die y-Pixel-Koordinate des Bildes ermitteln.quelle
jQuery .offset () ruft die aktuellen Koordinaten des ersten Elements ab oder legt die Koordinaten jedes Elements in der Gruppe der übereinstimmenden Elemente relativ zum Dokument fest.
quelle
Ich habe die Antwort von @ meouw genommen, in der clientLeft hinzugefügt, die den Rand zulässt, und dann drei Versionen erstellt:
getAbsoluteOffsetFromBody - Ähnlich wie bei @ meouw wird hier die absolute Position relativ zum Hauptteil oder HTML-Element des Dokuments abgerufen (abhängig vom Mackenmodus).
getAbsoluteOffsetFromGivenElement - gibt die absolute Position relativ zum angegebenen Element (relativeEl) zurück. Beachten Sie, dass das angegebene Element das Element el enthalten muss. Andernfalls verhält es sich genauso wie getAbsoluteOffsetFromBody. Dies ist nützlich, wenn zwei Elemente in einem anderen (bekannten) Element enthalten sind (optional mehrere Knoten im Knotenbaum) und diese an derselben Position positionieren möchten.
getAbsoluteOffsetFromRelative - Gibt die absolute Position relativ zum ersten übergeordneten Element mit position: relative zurück. Dies ähnelt getAbsoluteOffsetFromGivenElement aus demselben Grund, geht jedoch nur bis zum ersten übereinstimmenden Element.
Wenn Sie immer noch Probleme haben, insbesondere beim Scrollen, können Sie sich http://www.greywyvern.com/?post=331 ansehen. Ich habe mindestens einen fragwürdigen Code in getStyle bemerkt, der in Ordnung sein sollte, vorausgesetzt, die Browser verhalten sich , aber den Rest habe ich überhaupt nicht getestet.
quelle
Wenn Sie jQuery verwenden, das Dimensions-Plugin hervorragend und ermöglicht es Ihnen, genau anzugeben, was Sie möchten.
z.B
Relative Position, absolute Position, absolute Position ohne Polsterung, mit Polsterung ...
Es geht weiter, sagen wir einfach, Sie können viel damit anfangen.
Der Vorteil der Verwendung von jQuery ist außerdem die geringe Dateigröße und die einfache Verwendung. Ohne jQuery können Sie danach nicht mehr auf JavaScript zurückgreifen.
quelle
Dies ist der beste Code, den ich erstellt habe (funktioniert auch in iframes, im Gegensatz zu jQuerys offset ()). Das Webkit scheint sich etwas anders zu verhalten.
Basierend auf meouws Kommentar:
quelle
jQuery
zu verwenden$.browser.webkit
; Sie müssen herumspielen, umnavigator.userAgent
dasselbe mit pure zu tunJavaScript
.Wenn Sie jQuery verwenden, kann dies eine einfache Lösung sein:
quelle
Unterschied zwischen klein und klein
Schauen Sie sich ein Beispiel für Koordinaten an: http://javascript.info/tutorial/coordinates
quelle
<svg>
Elemente, zum Beispiel, haben nichtoffsetLeft
,offsetTop
undoffsetParent
Eigenschaften.DIV
oderIMG
nichtSVG
. "Beispielkoordinaten anzeigen"? Sie können das Objekt svg als Positionsaufruf getOffsetRect finden. Versuchen Sie, die Objektarbeit abhängig zu machen.Der sauberste Ansatz, den ich gefunden habe, ist eine vereinfachte Version der von jQuery's verwendeten Technik
offset
. Ähnlich wie bei einigen anderen Antworten beginnt es mitgetBoundingClientRect
; Es verwendet dann daswindow
und dasdocumentElement
, um die Bildlaufposition sowie Dinge wie den Rand auf dembody
(oft die Standardeinstellung) anzupassen .Code-Snippet anzeigen
quelle
Während dies bei so vielen Antworten sehr wahrscheinlich verloren geht, haben die Top-Lösungen hier bei mir nicht funktioniert.
Soweit ich das beurteilen konnte, hätte keine der anderen Antworten geholfen.
Situation :
Auf einer HTML5-Seite hatte ich ein Menü, das ein Navigationselement in einem Header war (nicht DER Header, sondern ein Header in einem anderen Element).
Ich wollte, dass die Navigation oben bleibt, sobald ein Benutzer zu ihr gescrollt hat, aber zuvor war die Kopfzeile absolut positioniert (damit ich sie etwas anderes leicht überlagern kann).
Die oben genannten Lösungen haben nie eine Änderung ausgelöst, da sich .offsetTop nicht ändern würde, da dies ein absolut positioniertes Element war. Zusätzlich war die .scrollTop-Eigenschaft einfach die Spitze des obersten Elements ... das heißt 0 und wäre immer 0.
Alle Tests, die ich mit diesen beiden durchgeführt habe (und die gleichen mit den Ergebnissen von getBoundingClientRect), haben mir nicht gesagt, ob der obere Rand der Navigationsleiste jemals zum oberen Rand der sichtbaren Seite gescrollt hat (wie in der Konsole angegeben, blieben sie beim Scrollen einfach die gleichen Zahlen aufgetreten).
Lösung
Die Lösung für mich war die Verwendung
Der Wert der pageTop-Eigenschaft spiegelt den sichtbaren Bereich des Bildschirms wider, sodass ich verfolgen kann, wo sich ein Element in Bezug auf die Grenzen des sichtbaren Bereichs befindet.
Es ist wahrscheinlich unnötig zu sagen, dass ich diese Lösung jedes Mal verwenden werde, wenn ich mich mit dem Scrollen beschäftige, um programmgesteuert auf die Bewegung von Elementen zu reagieren, die gescrollt werden.
Hoffe es hilft jemand anderem.
WICHTIGER HINWEIS: Dies scheint derzeit in Chrome und Opera zu funktionieren und definitiv nicht in Firefox (6-2018) ... bis Firefox VisualViewport unterstützt. Ich empfehle, diese Methode NICHT zu verwenden (und ich hoffe, dass sie es bald tun ... es macht viel sinnvoller als der Rest).
UPDATE:
Nur ein Hinweis zu dieser Lösung.
Während ich immer noch finde, dass das, was ich entdeckt habe, sehr wertvoll für Situationen ist, in denen "... programmgesteuert auf Bewegungen von Elementen reagiert wird, die gescrollt werden". anwendbar. Die bessere Lösung für das Problem, das ich hatte, war die Verwendung von CSS zum Einstellen Position: klebrigauf dem Element. Wenn Sie Sticky verwenden, kann ein Element ohne Verwendung von Javascript oben bleiben (
HINWEIS: Manchmal funktioniert dies nicht so effektiv wie das Ändern des Elements in "Fixed", aber für die meisten Anwendungen ist der Sticky-Ansatz wahrscheinlich überlegen.) UPDATE01:
Also habe ich das erkannt Für eine andere Seite hatte ich eine Anforderung, bei der ich die Position eines Elements in einem leicht komplexen Bildlauf-Setup ermitteln musste (Parallaxe plus Elemente, die als Teil einer Nachricht vorbeirollen). In diesem Szenario wurde mir klar, dass das Folgende den Wert lieferte, den ich verwendete, um zu bestimmen, wann etwas zu tun ist:
Hoffe, diese Antwort ist jetzt allgemeiner nützlich.
quelle
Ich habe es so gemacht, damit es mit alten Browsern kompatibel ist.
Weitere Informationen zu Koordinaten in JavaScript finden Sie hier: http://javascript.info/tutorial/coordinates
quelle
Um den Gesamtversatz eines Elements zu erhalten, können Sie alle übergeordneten Versätze rekursiv zusammenfassen:
Mit dieser Dienstprogrammfunktion beträgt der gesamte obere Versatz eines dom-Elements:
quelle
Vielen Dank an ThinkingStiff für die Antwort , dies ist nur eine andere Version davon.
quelle
Ich habe die Lösung von Andy E erfolgreich verwendet, um ein Bootstrap 2-Modal zu positionieren, je nachdem, auf welchen Link in einer Tabellenzeile ein Benutzer klickt. Die Seite ist eine Tapestry 5-Seite und das unten stehende Javascript wird in die Java-Seitenklasse importiert.
Javascript:
}}
Mein Modalcode:
Der Link in der Schleife:
Und der Java-Code in der Seitenklasse:
Hoffe das hilft jemandem, dieser Beitrag hat geholfen.
quelle
Nach vielen Recherchen und Tests scheint dies zu funktionieren
Siehe http://jsbin.com/xuvovalifo/edit?html,js,output
quelle
Ich dachte nur, ich würde das auch da rauswerfen.
Ich konnte es nicht in älteren Browsern testen, aber es funktioniert in den neuesten Top 3. :)
quelle
Da verschiedene Browser Rahmen, Auffüllungen, Ränder usw. auf unterschiedliche Weise rendern. Ich habe eine kleine Funktion geschrieben, um die oberen und linken Positionen eines bestimmten Elements in jedem gewünschten Stammelement in einer genauen Dimension abzurufen:
Um die linke Position abzurufen, müssen Sie Folgendes zurückgeben:
quelle
quelle
el.offsetTop
undel.offsetLeft
(das OP sagt nichts über jQuery ... Ich bin nicht sicher, warum Ihre Antwort auch jQuery verwendet ...)