Récupérer la position (X, Y) d'un élément HTML

Je veux savoir comment obtenir la position X et Y des éléments HTML tels que img et div en JavaScript.

L'approche correcte consiste à utiliser element.getBoundingClientRect() :

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

Internet Explorer a soutenu cela depuis tant que vous êtes susceptible de vous préoccuper et il a été finalement standardisé dans CSSOM Views . Tous les autres navigateurs l'ont adopté depuis longtemps .

Certains navigateurs renvoient également des propriétés de hauteur et de largeur, mais cela n'est pas standard. Si vous êtes préoccupé par la compatibilité plus ancienne du navigateur, vérifiez les révisions de cette réponse pour une implémentation dégradée optimisée.

Les valeurs renvoyées par element.getBoundingClientRect() sont relatives à la fenêtre. Si vous en avez besoin par rapport à un autre élément, il suffit de soustraire un rectangle de l'autre:

 var bodyRect = document.body.getBoundingClientRect(), elemRect = element.getBoundingClientRect(), offset = elemRect.top - bodyRect.top; alert('Element is ' + offset + ' vertical pixels from <body>'); 

Les bibliothèques utilisent certaines étapes pour obtenir des décalages précis pour un élément.
Voici une fonction simple qui fait le travail dans toutes les circonstances que j'ai essayé.

 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; 

Cela a fonctionné pour moi (modifié de la meilleure réponse votée):

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

En utilisant cela, nous pouvons appeler

 getOffset(element).left 

ou

 getOffset(element).top 

Si la page comprend – au moins – toute "DIV", la fonction donnée par meouw jette la valeur "Y" au-delà des limites de la page actuelle. Pour trouver la position exacte, vous devez gérer à la fois "offsetParent" et "parentNode" s.

Essayez le code donné ci-dessous (il est vérifié pour 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]; }; 

Vous pouvez ajouter deux propriétés à Element.prototype pour obtenir la partie supérieure / gauche de n'importe quel élément.

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

Cela s'appelle comme ceci:

 var x = document.getElementById( 'myDiv' ).documentOffsetLeft; 

Voici une démonstration comparant les résultats au offset().top de jQuery offset().top et .left : http://jsfiddle.net/ThinkingStiff/3G7EZ/

Pour récupérer efficacement le poste par rapport à la page, et sans utiliser une fonction récursive: (inclut IE aussi)

 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; 

Vous pourriez être mieux servi en utilisant un cadre JavaScript, qui a des fonctions pour renvoyer ces informations (et bien plus encore!) De manière indépendante du navigateur. Voici quelques-uns:

  • Prototype
  • JQuery
  • MooTools
  • YUI (yahoo)

Avec ces cadres, vous pouvez faire quelque chose comme: $('id-of-img').top pour obtenir la coordonnée y-pixel de l'image.

Les éléments HTML de la plupart des navigateurs auront: –

 offsetLeft offsetTop 

Ceux-ci spécifient la position de l'élément par rapport à son parent le plus proche qui a une mise en page. Ce parent peut souvent être accédé à bif la propriété offsetParent.

IE et FF3 ont

 clientLeft clientTop 

Ces propriétés sont moins fréquentes, elles spécifient une position d'élément avec la zone client de ses parents (la zone rembourrée fait partie de la zone client mais la bordure et la marge ne l'est pas).

JQuery .offset () obtiendra les coordonnées actuelles du premier élément ou définira les coordonnées de chaque élément dans l'ensemble des éléments correspondants par rapport au document.

Si vous utilisez jQuery, le plugin de dimensions est excellent et vous permet de spécifier exactement ce que vous voulez.

par exemple

Position relative, position absolue, position absolue sans rembourrage, avec rembourrage …

Cela continue, disons qu'il y a beaucoup de choses à faire avec ça.

De plus, le bonus d'utilisation de jQuery est une taille de fichier légère et une utilisation facile, vous ne reviendrez pas sur JavaScript sans plus tard.

J'ai pris la réponse de @ meouw, ajouté dans le clientLeft qui permet la bordure, puis crée trois versions:

GetAbsoluteOffsetFromBody – similaire à @ meouw's, cela obtient la position absolue par rapport au corps ou à l'élément html du document (selon le mode de quirks)

GetAbsoluteOffsetFromGivenElement – renvoie la position absolue par rapport à l'élément donné (relativeEl). Notez que l'élément donné doit contenir l'élément el, ou ce sera le même que getAbsoluteOffsetFromBody. Ceci est utile si vous avez deux éléments contenus dans un autre élément (connu) (éventuellement plusieurs nœuds dans l'arbre des noeuds) et souhaitez les faire la même position.

GetAbsoluteOffsetFromRelative – renvoie la position absolue par rapport au premier élément parent avec la position: relative. Ceci est similaire à getAbsoluteOffsetFromGivenElement, pour la même raison, mais n'entrera que dans le premier élément correspondant.

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

Si vous rencontrez toujours des problèmes, en particulier en ce qui concerne le défilement, vous pouvez essayer de consulter http://www.greywyvern.com/?post=331 – J'ai remarqué au moins un code douteux dans getStyle qui devrait être bien en supposant que les navigateurs se comportent , Mais n'ont pas testé le reste du tout.

Que ce soit de quelque chose comme ça, en passant l'ID de l'élément et il renverra le gauche ou le haut, on peut les combiner:

1) trouver à gauche

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

2) trouver le top

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

Ou 3) trouver la gauche et le haut ensemble

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

C'est le meilleur code que j'ai réussi à créer (fonctionne également dans les iframes, contrairement au décalage de jQuery ()). Le Webkit semble avoir un comportement différent.

Basé sur le commentaire 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 }; } 

Si vous utilisez jQuery, cela pourrait être une solution simple:

 <script> var el = $("#element"); var position = el.position(); console.log( "left: " + position.left + ", top: " + position.top ); </script> 

L'approche la plus propre que j'ai trouvée est une version simplifiée de la technique utilisée par le offset de jQuery. Comme pour certaines des autres réponses, il commence par getBoundingClientRect ; Il utilise ensuite la window et le documentElement pour régler la position de défilement ainsi que des choses comme la marge sur le body (souvent la valeur par défaut).

 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> 

Différence entre petit et petit

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

Regardez un exemple de coordonnées: http://javascript.info/tutorial/coordinates

Je l'ai fait comme ça, donc c'était compatible avec les anciens navigateurs.

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

En savoir plus sur les coordonnées en JavaScript ici: http://javascript.info/tutorial/coordinates

J'ai utilisé avec succès la solution d'Andy E pour positionner un mode 2 de bootstrap selon le lien dans une rangée de table sur laquelle un utilisateur clique. La page est une page Tapestry 5 et javascript ci-dessous est importé dans la classe java.

Javascript:

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

}

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

Le lien dans la boucle:

 <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"> <at: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> 

Et le code java dans la classe de 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');"); } }); } 

J'espère que cela aide quelqu'un, ce post a aidé.

Je pensais juste que je lâcherais cela aussi.
Je n'ai pas pu le tester dans les navigateurs plus anciens, mais ça marche dans le dernier des trois meilleurs. 🙂

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

Après de nombreuses recherches et essais, cela semble fonctionner

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

Voir http://jsbin.com/xuvovalifo/edit?html,js,output

Étant donné que différents navigateurs rendent la bordure, le rembourrage, la marge et etc. de manière différente. J'ai écrit une petite fonction pour récupérer les positions supérieure et gauche de l'élément spécifique dans chaque élément racine que vous voulez en dimension précise:

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

Pour récupérer la position de gauche, vous devez retourner:

  return offsetRect.left - rootRect.left;