Obtenir la position d'une balise div / span

103

Quelqu'un peut-il me montrer comment obtenir la top& leftposition d'un élément divou spanquand on n'est pas spécifié?

c'est à dire:

<span id='11a' style='top:55px;' onmouseover="GetPos(this);">stuff</span>
<span id='12a' onmouseover="GetPos(this);">stuff</span>

Dans ce qui précède, si je fais:

document.getElementById('11a').style.top

La valeur de 55pxest renvoyée. Cependant, si j'essaye cela pour span«12a», alors rien n'est retourné.

J'ai un tas de div/ spans sur une page pour laquelle je ne peux pas spécifier les propriétés top/ left, mais je dois afficher un divdirectement sous cet élément.

Schmoopy
la source

Réponses:

100

Cette fonction vous indiquera la position x, y de l'élément par rapport à la page. En gros, vous devez parcourir tous les parents de l'élément et ajouter leurs décalages ensemble.

function getPos(el) {
    // yay readability
    for (var lx=0, ly=0;
         el != null;
         lx += el.offsetLeft, ly += el.offsetTop, el = el.offsetParent);
    return {x: lx,y: ly};
}

Cependant, si vous vouliez simplement la position x, y de l'élément par rapport à son conteneur, alors tout ce dont vous avez besoin est:

var x = el.offsetLeft, y = el.offsetTop;

Pour placer un élément directement en dessous de celui-ci, vous devrez également connaître sa hauteur. Ceci est stocké dans la propriété offsetHeight / offsetWidth.

var yPositionOfNewElement = el.offsetTop + el.offsetHeight + someMargin;
nickf
la source
5
Malheureusement, cette méthode échoue dans Chrome lorsque l'élément se trouve dans un tableau avec une bordure. Il échouera également en mode standard IE6 en raison des marges BODY.
GetFree
1
Juste un avertissement pour les utilisateurs de ce code. Ceci est relatif à la page et non à la fenêtre. Il renvoie la même valeur si l'utilisateur fait défiler en utilisant les barres de défilement. Faites attention.
Isaac Bolinger
merci @IsaacBolinger vient de le remarquer. Quelqu'un peut-il me dire comment je peux changer les valeurs lorsque la fenêtre est redimensionnée ou que l'utilisateur fait défiler?
David Fariña le
@ DavidFariña J'ai utilisé le module de géométrie "dom-geometry" du dojo pour cela. Je ne sais pas comment le faire nativement.
Isaac Bolinger
Downvoté - Cela peut être évident pour les utilisateurs plus expérimentés, mais vous n'avez pas spécifié exactement ce qui doit être transmis pour el (c.-à-d. Veuillez fournir un exemple d'utilisation).
Matt
184

Vous pouvez appeler la méthode getBoundingClientRect()sur une référence à l'élément. Ensuite , vous pouvez examiner les top, left, rightet / ou des bottompropriétés ...

var offsets = document.getElementById('11a').getBoundingClientRect();
var top = offsets.top;
var left = offsets.left;

Si vous utilisez jQuery, vous pouvez utiliser le code plus succinct ...

var offsets = $('#11a').offset();
var top = offsets.top;
var left = offsets.left;
Alex
la source
11
+1 pour cette réponse, getBoundingClientRect()devrait être utilisé - et cela devrait être la réponse acceptée! Mais vous n'avez pas besoin d'un "navigateur moderne" pour que cela fonctionne, consultez la liste de compatibilité que j'ai montrée ici: stackoverflow.com/questions/1480133/… . Cela fonctionne bien dans IE 4.0+ (!), Chrome 1.0+, FF 3.0+, Safari 4.0+ et Opera.
Sk8erPeter
25
Notez que getBoundingClientRect()renvoie des valeurs relatives à la fenêtre, pas au document. Pour cela, vous voudriez quelque chose comme top = el.getBoundingClientRect().top + window.pageYOffset - el.ownerDocument.documentElement.clientTop.
Zack Bloom
1
Notez également que getBoundingClientRectprend transformen compte.
ExpExc
Ce n'est pas exact si le premier enfant non positionné de manière absolue a une marge supérieure ou une marge gauche. Il n'y a actuellement aucune solution précise sur cette page, donc si quelqu'un le sait, veuillez poster une réponse.
Curtis
16

Alors que la réponse de @ nickf fonctionne. Si vous n'aimez pas les anciens navigateurs, vous pouvez utiliser cette version Javascript pur. Fonctionne dans IE9 + et autres

var rect = el.getBoundingClientRect();

var position = {
  top: rect.top + window.pageYOffset,
  left: rect.left + window.pageXOffset
};
Benjamin Intal
la source
12

Comme Alex l'a noté, vous pouvez utiliser jQuery offset () pour obtenir la position par rapport au flux de documents. Utilisez position () pour ses coordonnées x, y par rapport au parent.

EDIT: Switched document.readypour window.loadcause d' loadattente pour tous les éléments afin que vous obteniez leur taille au lieu de préparer simplement le DOM. D'après mon expérience, il en loadrésulte moins d'éléments mal positionnés en Javascript.

$(window).load(function(){ 
  // Log the position with jQuery
  var position = $('#myDivInQuestion').position();
  console.log('X: ' + position.left + ", Y: " + position.top );
});
Dylan Valade
la source
9

Pour tous ceux qui n'ont besoin que de la position en haut ou à gauche, de légères modifications du code lisible de @ Nickf font l'affaire.

function getTopPos(el) {
    for (var topPos = 0;
        el != null;
        topPos += el.offsetTop, el = el.offsetParent);
    return topPos;
}

et

function getLeftPos(el) {
    for (var leftPos = 0;
        el != null;
        leftPos += el.offsetLeft, el = el.offsetParent);
    return leftPos;
}
Jens Frandsen
la source
2

Je me rends compte que c'est un vieux fil de discussion, mais la réponse de @alex doit être marquée comme la bonne réponse

element.getBoundingClientRect() est une correspondance exacte avec jQuery $(element).offset()

Et il est compatible avec IE4 + ... https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect

lukeed
la source
Vous devrez inclure le décalage de défilement de la page
Benjamin Intal