j'avais utilisé ces 7 lignes de code qui fonctionnent dans tous les navigateurs avec des divergences dans ie5,6,7 (je ne me souviens pas avoir eu de problème ... peut être du type doc) ... quirksmode.org/js/findpos. html et je l'utilisais beaucoup depuis tant d'années. peut être sombody peut pointer les défauts le cas échéant.
Jayapal Chandran
99
@AnthonyWJones, je suppose que vous aviez besoin du plaisir pédant, mais il est évident, comme c'est toujours le cas non spécifié, que l'OP se réfère au cas le plus général, ou se réfère aux coordonnées de la fenêtre du navigateur.
Motes
7
@Mote, non, ce n'est pas si évident. Laisser de côté l'inférence, la subjectivité et les faux axiomes. Il peut être relatif à la fenêtre d'affichage ou au haut de la page (alias document.documentElement).
Andre Figueiredo
16
Par défaut, le plus général n'est pas une inférence, c'est la progression logique, donc ce serait relatif à la fenêtre, ou "haut de page" pourrait être le terme comme vous le dites. Dans la théorie des jeux, il est codifié comme un concept appelé point de Schelling. Assurez-vous de préciser quand vous ne voulez pas parler du cas le plus général.
var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);
Internet Explorer prend en charge cela depuis aussi longtemps que vous vous en souciez et il a finalement été normalisé dans les vues CSSOM . Tous les autres navigateurs l'ont adopté il y a longtemps .
Certains navigateurs renvoient également des propriétés de hauteur et de largeur, bien que ce ne soit pas standard. Si vous êtes préoccupé par la compatibilité des anciens navigateurs, consultez 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, soustrayez simplement 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>');
Ne fonctionne pas ... c'est 8 pixels à la verticale et à l'horizontale, en raison de la marge de 8 pixels dans le corps. La solution de Meouw fonctionne parfaitement. Si vous voulez, j'ai un petit test pour démontrer le problème.
CpnCrunch du
3
En fait, je pense que cela dépend de ce que vous voulez réellement obtenir. La question est un peu ambiguë. Votre réponse est correcte si vous voulez juste les coordonnées par rapport à la fenêtre ou par rapport à l'élément body, mais cela ne vous aide pas dans le cas où vous voulez la position absolue de l'élément (ce que j'imagine est ce que la plupart des gens veulent) . La réponse de meouw ne vous donne pas cela non plus, sauf si vous supprimez les bits '-scrollLeft' et '-scrollTop'.
CpnCrunch du
4
@CpnCrunch: Je vois ce que tu veux dire maintenant; Je ne savais pas que vous faisiez référence à la dernière partie de ma réponse. Lorsque le corps a une marge, son cadre de délimitation sera compensé par ce nombre de pixels de chaque côté respectif. Dans ce cas, vous devez également soustraire le style de marge calculé des coordonnées du corps. Il convient de noter que les réinitialisations CSS suppriment la marge <body>, cependant.
Andy E
3
element.getBoundingClientRect().topne renvoie pas le décalage supérieur correct dans le cas d'un position: fixedélément dans iOS (iPhone 8) s'il contient un élément d'entrée focalisé et que le clavier virtuel a glissé vers le haut. Par exemple, si le décalage réel par rapport au haut de la fenêtre est de 200 pixels, il le signalera comme 420 pixels, où 220 pixels est la hauteur du clavier virtuel. Si vous définissez l'élément position: absoluteet le positionnez à la même position que s'il était fixe, vous obtiendrez les 200 pixels corrects. Je ne connais pas de solution à cela.
Jānis Elmeris
327
Les bibliothèques vont jusqu'à certaines longueurs 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ées.
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;
changez: el = el.parentNode en: el = el.offsetParent; et cela semble fonctionner pour les iframes imbriqués maintenant ... Je pense que c'est ce que vous vouliez?
Adam
4
Cette solution est incomplète. Essayez de mettre une bordure épaisse sur un div et imbriquez-le plusieurs fois. Dans n'importe quelle version de Firefox (2-5), il sera désactivé par la largeur de bordure (même en mode de conformité aux normes).
ck_
3
n'y a-t-il pas une façon plus propre de le faire, comme une fonction el.totalOffsetLeft et totalOffsetTop? jQuery a certainement cette option mais c'est dommage qu'il n'y ait pas de méthode officielle pour cela, devons-nous attendre DOM4? Je suis en train de créer une application HTML5 canvas, donc je pense que la meilleure solution serait d'insérer un élément canvas dans un iframe afin que je puisse obtenir de vraies coordonnées avec clientX et clientY lorsque nous cliquons sur l'élément.
baptx
1
Donc, @Adam et meouw, dites-vous que le premier bloc de code est incorrect? Alors pourquoi ne pas supprimer tout cela? (Cette question a vu pas mal de téléspectateurs au fil des ans; peut-être bien d'enlever des choses s'ils se trompent?)
Arjan
2
@baptx: Je sais que c'est une réponse tardive, mais je n'ai pas vu votre commentaire plus tôt. Voir ma réponse ci-dessous pour une alternative plus conforme aux normes - vous n'avez même pas vraiment besoin du code de secours, car les navigateurs le prennent en charge depuis longtemps.
Andy E
242
Cela a fonctionné pour moi (modifié à partir de la réponse la plus votée):
function getOffset(el){const rect = el.getBoundingClientRect();return{
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};}
Seule cette solution fonctionne pour moi lorsque l'élément est placé dans divle centre à l'aide de CSS top:50%, left:50%; transform:translate(-50%, -50%);... excellent. D'accord avec la question @ScottBiggs. La logique est de rechercher la simplicité.
nelek
3
peut-être que ce n'est pas un gagnant car c'est la même chose que la solution d'Andy E, mais ne fonctionne pas dans les anciens navigateurs <IE9
niltoid
getBoundingClientRect provoque un pic de repeinture massif dans mes graphiques de performances
frumbert
1
Vous devez définir l' rectaide var, letou const. Sinon, il est défini comme window.rect.
hev1
2
left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)renverra la position médiane d'un élément
abhishake
97
Si vous voulez que cela se fasse uniquement en javascript , voici quelques doublons utilisantgetBoundingClientRect()
window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y
window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X
La première ligne renverra offsetTopdire Y par rapport au document. La deuxième ligne renverra offsetLeftdisons X par rapport au document.
getBoundingClientRect() est une fonction javascript qui renvoie la position de l'élément par rapport à la fenêtre d'affichage de la fenêtre.
Cela devrait être la solution. Il n'y a pas de code long ici, c'est compréhensible et très précis!
E Alexis MT
2
que faire si l'élément se trouve dans un élément déroulant? La seule façon de le faire est de additionner offsetTop de tous les éléments parents, comme d'autres réponses le suggèrent
Dmitri Pisarev
Comme l'affirme Dmitri, ceci est incorrect et très imparfait. Il ne devrait pas avoir autant de votes positifs que lui. Il sera TOUJOURS également dans un élément défilable car le document lui-même peut être défilé. En d'autres termes, à moins que le document entier ne rentre dans la fenêtre, il sera toujours incorrect si l'utilisateur a fait défiler la fenêtre principale.
Lev
46
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 disposition. Ce parent est souvent accessible via la propriété offsetParent.
IE et FF3 ont
clientLeft
clientTop
Ces propriétés sont moins courantes, elles spécifient une position des éléments avec sa zone cliente parents (la zone rembourrée fait partie de la zone cliente mais pas la bordure et la marge).
Si la page inclut - au moins - tout "DIV", la fonction donnée par meouw jette la valeur "Y" au-delà des limites de page actuelles. Afin de trouver la position exacte, vous devez gérer à la fois offsetParent et parentNode.
Essayez le code donné ci-dessous (il est vérifié pour FF2):
comme avec les autres solutions, même avec FF 24.4, le code ci-dessus ne fonctionne pas lorsque des largeurs de bordure existent dans le cadre de la disposition de positionnement.
voler
Vous êtes un épargnant de vie. Je travaille sur quelques bugs GWT assez profonds en ce moment et le jeter dans une méthode JSNI résout tous mes problèmes !!
Will Byrne
35
Vous pouvez ajouter deux propriétés pour Element.prototypeobtenir le haut / gauche de n'importe quel élément.
la modification Element.prototypeest généralement considérée comme une mauvaise idée . Cela rend le code très difficile à maintenir. De plus, ce code ne tient pas compte du défilement.
Jared Forsyth
23
Pour récupérer efficacement la position par rapport à la page, et sans utiliser de fonction récursive: (inclut également 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;
L'inclusion du tout important scrollTop / scrollLeft rend cette réponse un peu plus correcte.
scunliffe
19
Que diriez-vous de quelque chose comme ça, en passant l'ID de l'élément et il retournera la gauche ou le haut, nous pouvons également 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 gauche et 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');
Vous pourriez être mieux servi en utilisant un framework JavaScript, qui a des fonctions pour renvoyer ces informations (et bien plus encore!) De manière indépendante du navigateur. Voici quelques-uns:
@Costa Ils utilisent tous ce type de fonctions, bien qu'il s'agisse d'un domaine en évolution, car les différents navigateurs se conforment différemment à la spécification. Une grande partie du code traite de la "correction" des problèmes. Vous devriez vraiment regarder le code source.
Shalom Craimer
18
@scraimer: jQuery et YUI ne sont PAS des frameworks !!! Ce sont des bibliothèques ! Ce n'est pas la même chose. Citant jquery.com : "jQuery est une bibliothèque JavaScript rapide, petite et riche en fonctionnalités ." Citant yuilibrary.com (vous pouvez aussi voir le mot "magique" dans l'URL ...): "YUI est une bibliothèque JavaScript et CSS open source gratuite pour créer des applications Web riches en interactivité."
Sk8erPeter
29
Vous devez donc utiliser d'énormes bibliothèques uniquement pour cette tâche simple? Pas nécessaire. Je déteste que chaque fois que je veux faire quelque chose avec js, j'obtiens ces solutions jQuery. jQuery n'est pas JS!
Opptatt Jobber
1
@OpptattJobber Je suis d'accord ... JQuery n'est pas javascript. Il s'appuie sur Javascript mais c'est un langage de programmation complètement différent.
Nick Manning
5
@NickManning Ce n'est pas un nouveau langage, c'est une couche d'abstraction pour le DOM qui élimine d'avoir à écrire des solutions de contournement de compatibilité et de performances directement dans votre code. Si vous n'utilisez pas jQuery, vous devez de toute façon utiliser un type de couche d'abstraction.
Ginman
15
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.
Pour une raison quelconque, il ne donne pas les mêmes résultats dans IE que les autres navigateurs. Je pense que dans IE, il donne une position par rapport à la fenêtre, donc si vous faites défiler, vous obtiendrez des résultats différents dans IE par rapport aux autres
Abdul Rahim Haddad
1
offset () est confondu par le zoom, au moins dans Android Chrome, il est donc inutile. stackoverflow.com/a/11396681/1691517 montre une manière tolérante au zoom.
Timo Kähkönen
10
J'ai pris la réponse de @ meouw, ajouté dans le clientLeft qui permet la frontière, puis créé trois versions:
getAbsoluteOffsetFromBody - similaire à @ meouw, cela obtient la position absolue par rapport au corps ou à l'élément html du document (selon le mode excentrique)
getAbsoluteOffsetFromGivenElement - retourne la position absolue par rapport à l'élément donné (relativeEl). Notez que l'élément donné doit contenir l'élément el, sinon cela se comportera de la même manière que getAbsoluteOffsetFromBody. Cela est utile si vous avez deux éléments contenus dans un autre élément (connu) (éventuellement plusieurs nœuds dans l'arborescence des nœuds) et que vous souhaitez leur donner la même position.
getAbsoluteOffsetFromRelative - renvoie la position absolue par rapport au premier élément parent avec position: relative. Ceci est similaire à getAbsoluteOffsetFromGivenElement, pour la même raison, mais n'ira que jusqu'au premier élément correspondant.
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 };}
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 morceau de code discutable dans getStyle qui devrait être correct en supposant que les navigateurs se comportent , mais je n'ai pas testé le reste du tout.
Intéressant ... mais sur Edge getAbsoluteOffsetFromBody (element) .top renvoie une valeur différente lorsque je défile, dans Chrome, il reste cohérent pendant que je défile. Il semble qu'Edge s'ajuste avec la position du défilement. Lorsque l'élément est déroulé hors de la vue, j'obtiens une valeur négative.
Norman
getAbsoluteOffsetFromRelative a fait ma journée, j'ai dû reproduire l'info-bulle bootstrap sans Javascript de bootstrap, cela m'a beaucoup aidé.
Nolyurn
Au cas où Meouw changerait de nom d'utilisateur, liez le lien pour répondre: stackoverflow.com/a/442474/3654837 . (Je ne veux pas cogner ce vieux fil alors oui, je mets en commentaire)
Mukyuu
8
si vous utilisez jQuery, le plugin 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 simplement qu'il y a beaucoup à faire.
De plus, l'avantage de jQuery est sa taille de fichier légère et son utilisation facile, vous ne reviendrez pas à JavaScript sans cela par la suite.
C'est le meilleur code que j'ai réussi à créer (fonctionne également dans les iframes, contrairement à l'offset () de jQuery). Il semble que le webkit ait un comportement légèrement différent.
D'après 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/safariif($.browser.webkit){
el = el.parentNode;}else{// firefox/IE
el = el.offsetParent;}}return{ top: _y, left: _x };}
Notez que vous devrez jQueryutiliser $.browser.webkit; Vous devrez jouer avec navigator.userAgentpour faire de même avec pure JavaScript.
SP
2
$ .browser n'est plus disponible dans la dernière version de jQuery
Gus
malheureusement, même avec FF 24.4, le code ci-dessus ne fonctionne pas lorsque des largeurs de bordure existent dans le cadre de la disposition de positionnement.
voler
8
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>
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 };}
Cela ne fonctionne malheureusement pas pour tous les éléments que l'on peut trouver dans un document HTML moderne. Embarqués <svg>éléments, par exemple, ne sont pas offsetLeft, offsetTopet les offsetParentpropriétés.
Jonathan Eunice
C'est juste DIVou IMGpas SVG. Voir "Regardez un exemple de coordonnées"? vous pouvez trouver l'objet svg est l'appel de position getOffsetRect , essayez de dépendre du travail de l'objet.
KingRider
7
L'approche la plus propre que j'ai trouvée est une version simplifiée de la technique utilisée par jQuery offset. Semblable à certaines des autres réponses, il commence par getBoundingClientRect; il utilise ensuite le windowet le documentElementpour ajuster la position du défilement ainsi que des éléments comme la marge sur le body(souvent la valeur par défaut).
Bien que cela soit très probablement perdu au bas de tant de réponses, les meilleures solutions ici ne fonctionnaient pas pour moi.
Pour autant que je sache, aucune des autres réponses n'aurait aidé.
Situation :
dans une page HTML5, j'avais un menu qui était un élément nav à l'intérieur d'un en-tête (pas l'en-tête mais un en-tête dans un autre élément).
Je voulais que la navigation reste en haut une fois qu'un utilisateur y avait fait défiler, mais avant cela, l'en-tête était positionné de manière absolue (donc je pouvais le superposer quelque chose d'autre).
Les solutions ci-dessus n'ont jamais déclenché de changement car .offsetTop n'allait pas changer car il s'agissait d'un élément positionné en absolu. De plus, la propriété .scrollTop était simplement le haut de l'élément le plus haut ... c'est-à-dire 0 et serait toujours 0.
Tous les tests que j'ai effectués en utilisant ces deux (et la même chose avec les résultats de getBoundingClientRect) ne me diraient pas si le haut de la barre de navigation a jamais défilé vers le haut de la page visible (encore une fois, comme indiqué dans la console, ils sont simplement restés les mêmes chiffres pendant le défilement eu lieu).
Solution
La solution pour moi était d'utiliser
window.visualViewport.pageTop
La valeur de la propriété pageTop reflète la section visible de l'écran, ce qui me permet donc de suivre où un élément se réfère aux limites de la zone visible.
Il est probablement inutile de le dire, chaque fois que je traite du défilement, je m'attends à utiliser cette solution pour répondre par programmation au mouvement des éléments défilés.
J'espère que cela aide quelqu'un d'autre.
REMARQUE IMPORTANTE: cela semble fonctionner dans Chrome et Opera actuellement et certainement pas dans Firefox (6-2018) ... jusqu'à ce que Firefox prenne en charge visualViewport, je recommande de NE PAS utiliser cette méthode, (et j'espère qu'ils le feront bientôt ... cela fait beaucoup plus de sens que les autres).
MISE À JOUR:
Juste une note concernant cette solution. Bien que je trouve toujours ce que j'ai découvert très utile pour les situations dans lesquelles "... répondre par programmation au mouvement des éléments en cours de défilement". est applicable. La meilleure solution au problème que j'avais était d'utiliser CSS pour définir position: collantsur l'élément. En utilisant sticky, vous pouvez laisser un élément en haut sans utiliser javascript (REMARQUE: il y a des moments où cela ne fonctionnera pas aussi efficacement que de changer l'élément en fixe, mais pour la plupart des utilisations, l'approche collante sera probablement supérieure)
UPDATE01:
J'ai donc réalisé que pour une page différente, j'avais une exigence où je devais détecter la position d'un élément dans une configuration de défilement légèrement complexe (parallaxe plus éléments qui défilent dans le cadre d'un message). J'ai réalisé dans ce scénario que les éléments suivants fournissaient la valeur que j'utilisais pour déterminer quand faire quelque chose:
cela est très susceptible d'être au sommet de tant de réponses lorsque vous cliquez sur actif pour trier les réponses
lucchi
@lucchi: Eh bien, je suppose que je pourrais supprimer le texte @ en haut ... même si je me suis retrouvé sur celui-ci à nouveau et j'ai réalisé que j'avais trouvé une meilleure solution à mon propre problème ... bien que ma réponse soit plus note de bas de page pour les réponses plus complètes. Je soupçonne que mes exigences n'étaient peut-être pas si courantes que les autres réponses ne fonctionnaient pas pour moi?
MER
1
J'apprécie votre réponse de toute façon, c'était juste pour vous dire que, quiconque veut savoir que vous avez écrit quelque chose de nouveau. Vous n'êtes pas seul ....
lucchi
5
Je l'ai fait comme ça, donc c'était compatible avec les anciens navigateurs.
// 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;}
J'ai utilisé avec succès la solution d'Andy E pour positionner un modal bootstrap 2 en fonction du lien dans une ligne de tableau sur lequel un utilisateur clique. La page est une page Tapestry 5 et le javascript ci-dessous est importé dans la classe de page java.
Ce code js m'a aidé, j'ai une ancienne application webforms utilisant plusieurs espaces réservés injectant des pages .aspx et je n'arrivais pas à comprendre comment ajouterChild () d'une boîte popup que je créais pour la mettre dans la fenêtre car l'arborescence DOM entière est détraquée avec les espaces réservés multiples et le balisage incorrect. Utiliser le body.getBoundingClientRect () puis utiliser son top dans le positionnement était ce dont j'avais besoin. Merci.
Brad Martin
1
Après de nombreuses recherches et tests, 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 };}
Étant donné que différents navigateurs affichent la bordure, le remplissage, la marge, 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 souhaitez dans une dimension précise:
Obtenez la position de div par rapport à gauche et en haut
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
J'ai voté contre parce que le bas et la droite ne sont pas des propriétés de décalage ()
MacroMan
@MacroMan, je respecte votre décision mais j'ai déjà expliqué dans le texte que "le code en bas et à droite n'est pas testé". De plus, je mettrai à jour mon code très bientôt.
Vishal
Je pense que c'est el.offsetTopet el.offsetLeft(l'OP ne dit rien sur jQuery ... Je ne sais pas pourquoi votre réponse utilise jQuery non plus ...)
Réponses:
La bonne approche consiste à utiliser
element.getBoundingClientRect()
:Internet Explorer prend en charge cela depuis aussi longtemps que vous vous en souciez et il a finalement été normalisé dans les vues CSSOM . Tous les autres navigateurs l'ont adopté il y a longtemps .
Certains navigateurs renvoient également des propriétés de hauteur et de largeur, bien que ce ne soit pas standard. Si vous êtes préoccupé par la compatibilité des anciens navigateurs, consultez 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, soustrayez simplement un rectangle de l'autre:la source
<body>
, cependant.element.getBoundingClientRect().top
ne renvoie pas le décalage supérieur correct dans le cas d'unposition: fixed
élément dans iOS (iPhone 8) s'il contient un élément d'entrée focalisé et que le clavier virtuel a glissé vers le haut. Par exemple, si le décalage réel par rapport au haut de la fenêtre est de 200 pixels, il le signalera comme 420 pixels, où 220 pixels est la hauteur du clavier virtuel. Si vous définissez l'élémentposition: absolute
et le positionnez à la même position que s'il était fixe, vous obtiendrez les 200 pixels corrects. Je ne connais pas de solution à cela.Les bibliothèques vont jusqu'à certaines longueurs 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ées.
la source
Cela a fonctionné pour moi (modifié à partir de la réponse la plus votée):
En utilisant cela, nous pouvons appeler
ou
la source
div
le centre à l'aide de CSStop:50%, left:50%; transform:translate(-50%, -50%);
... excellent. D'accord avec la question @ScottBiggs. La logique est de rechercher la simplicité.rect
aidevar
,let
ouconst
. Sinon, il est défini commewindow.rect
.left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)
renverra la position médiane d'un élémentSi vous voulez que cela se fasse uniquement en javascript , voici quelques doublons utilisant
getBoundingClientRect()
La première ligne renverra
offsetTop
dire Y par rapport au document. La deuxième ligne renverraoffsetLeft
disons X par rapport au document.getBoundingClientRect()
est une fonction javascript qui renvoie la position de l'élément par rapport à la fenêtre d'affichage de la fenêtre.la source
Les éléments HTML de la plupart des navigateurs auront: -
Ceux-ci spécifient la position de l'élément par rapport à son parent le plus proche qui a une disposition. Ce parent est souvent accessible via la propriété offsetParent.
IE et FF3 ont
Ces propriétés sont moins courantes, elles spécifient une position des éléments avec sa zone cliente parents (la zone rembourrée fait partie de la zone cliente mais pas la bordure et la marge).
la source
Si la page inclut - au moins - tout "DIV", la fonction donnée par meouw jette la valeur "Y" au-delà des limites de page actuelles. Afin de trouver la position exacte, vous devez gérer à la fois offsetParent et parentNode.
Essayez le code donné ci-dessous (il est vérifié pour FF2):
la source
Vous pouvez ajouter deux propriétés pour
Element.prototype
obtenir le haut / gauche de n'importe quel élément.Cela s'appelle comme ceci:
Voici une démo comparant les résultats à ceux de jQuery
offset().top
et.left
: http://jsfiddle.net/ThinkingStiff/3G7EZ/la source
Element.prototype
est généralement considérée comme une mauvaise idée . Cela rend le code très difficile à maintenir. De plus, ce code ne tient pas compte du défilement.Pour récupérer efficacement la position par rapport à la page, et sans utiliser de fonction récursive: (inclut également IE)
la source
Que diriez-vous de quelque chose comme ça, en passant l'ID de l'élément et il retournera la gauche ou le haut, nous pouvons également les combiner:
1) trouver à gauche
2) trouver le top
ou 3) trouver gauche et haut ensemble
la source
Vous pourriez être mieux servi en utilisant un framework JavaScript, qui a des fonctions pour renvoyer ces informations (et bien plus encore!) De manière indépendante du navigateur. Voici quelques-uns:
Avec ces cadres, vous pourriez faire quelque chose comme:
$('id-of-img').top
pour obtenir la coordonnée y-pixel de l'image.la source
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.
la source
J'ai pris la réponse de @ meouw, ajouté dans le clientLeft qui permet la frontière, puis créé trois versions:
getAbsoluteOffsetFromBody - similaire à @ meouw, cela obtient la position absolue par rapport au corps ou à l'élément html du document (selon le mode excentrique)
getAbsoluteOffsetFromGivenElement - retourne la position absolue par rapport à l'élément donné (relativeEl). Notez que l'élément donné doit contenir l'élément el, sinon cela se comportera de la même manière que getAbsoluteOffsetFromBody. Cela est utile si vous avez deux éléments contenus dans un autre élément (connu) (éventuellement plusieurs nœuds dans l'arborescence des nœuds) et que vous souhaitez leur donner la même position.
getAbsoluteOffsetFromRelative - renvoie la position absolue par rapport au premier élément parent avec position: relative. Ceci est similaire à getAbsoluteOffsetFromGivenElement, pour la même raison, mais n'ira que jusqu'au premier élément correspondant.
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 morceau de code discutable dans getStyle qui devrait être correct en supposant que les navigateurs se comportent , mais je n'ai pas testé le reste du tout.
la source
si vous utilisez jQuery, le plugin 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 simplement qu'il y a beaucoup à faire.
De plus, l'avantage de jQuery est sa taille de fichier légère et son utilisation facile, vous ne reviendrez pas à JavaScript sans cela par la suite.
la source
C'est le meilleur code que j'ai réussi à créer (fonctionne également dans les iframes, contrairement à l'offset () de jQuery). Il semble que le webkit ait un comportement légèrement différent.
D'après le commentaire de meouw:
la source
jQuery
utiliser$.browser.webkit
; Vous devrez jouer avecnavigator.userAgent
pour faire de même avec pureJavaScript
.Si vous utilisez jQuery, cela pourrait être une solution simple:
la source
Différence entre petit et petit
Regardez un exemple de coordonnées: http://javascript.info/tutorial/coordinates
la source
<svg>
éléments, par exemple, ne sont pasoffsetLeft
,offsetTop
et lesoffsetParent
propriétés.DIV
ouIMG
pasSVG
. Voir "Regardez un exemple de coordonnées"? vous pouvez trouver l'objet svg est l'appel de position getOffsetRect , essayez de dépendre du travail de l'objet.L'approche la plus propre que j'ai trouvée est une version simplifiée de la technique utilisée par jQuery
offset
. Semblable à certaines des autres réponses, il commence pargetBoundingClientRect
; il utilise ensuite lewindow
et ledocumentElement
pour ajuster la position du défilement ainsi que des éléments comme la marge sur lebody
(souvent la valeur par défaut).Afficher l'extrait de code
la source
Bien que cela soit très probablement perdu au bas de tant de réponses, les meilleures solutions ici ne fonctionnaient pas pour moi.
Pour autant que je sache, aucune des autres réponses n'aurait aidé.
Situation :
dans une page HTML5, j'avais un menu qui était un élément nav à l'intérieur d'un en-tête (pas l'en-tête mais un en-tête dans un autre élément).
Je voulais que la navigation reste en haut une fois qu'un utilisateur y avait fait défiler, mais avant cela, l'en-tête était positionné de manière absolue (donc je pouvais le superposer quelque chose d'autre).
Les solutions ci-dessus n'ont jamais déclenché de changement car .offsetTop n'allait pas changer car il s'agissait d'un élément positionné en absolu. De plus, la propriété .scrollTop était simplement le haut de l'élément le plus haut ... c'est-à-dire 0 et serait toujours 0.
Tous les tests que j'ai effectués en utilisant ces deux (et la même chose avec les résultats de getBoundingClientRect) ne me diraient pas si le haut de la barre de navigation a jamais défilé vers le haut de la page visible (encore une fois, comme indiqué dans la console, ils sont simplement restés les mêmes chiffres pendant le défilement eu lieu).
Solution
La solution pour moi était d'utiliser
La valeur de la propriété pageTop reflète la section visible de l'écran, ce qui me permet donc de suivre où un élément se réfère aux limites de la zone visible.
Il est probablement inutile de le dire, chaque fois que je traite du défilement, je m'attends à utiliser cette solution pour répondre par programmation au mouvement des éléments défilés.
J'espère que cela aide quelqu'un d'autre.
REMARQUE IMPORTANTE: cela semble fonctionner dans Chrome et Opera actuellement et certainement pas dans Firefox (6-2018) ... jusqu'à ce que Firefox prenne en charge visualViewport, je recommande de NE PAS utiliser cette méthode, (et j'espère qu'ils le feront bientôt ... cela fait beaucoup plus de sens que les autres).
MISE À JOUR:
Juste une note concernant cette solution.
Bien que je trouve toujours ce que j'ai découvert très utile pour les situations dans lesquelles "... répondre par programmation au mouvement des éléments en cours de défilement". est applicable. La meilleure solution au problème que j'avais était d'utiliser CSS pour définir position: collantsur l'élément. En utilisant sticky, vous pouvez laisser un élément en haut sans utiliser javascript (REMARQUE: il y a des moments où cela ne fonctionnera pas aussi efficacement que de changer l'élément en fixe, mais pour la plupart des utilisations, l'approche collante sera probablement supérieure)
UPDATE01:
J'ai donc réalisé que pour une page différente, j'avais une exigence où je devais détecter la position d'un élément dans une configuration de défilement légèrement complexe (parallaxe plus éléments qui défilent dans le cadre d'un message). J'ai réalisé dans ce scénario que les éléments suivants fournissaient la valeur que j'utilisais pour déterminer quand faire quelque chose:
J'espère que cette réponse est plus largement utile maintenant.
la source
Je l'ai fait comme ça, donc c'était compatible avec les anciens navigateurs.
Plus d'informations sur les coordonnées en JavaScript ici: http://javascript.info/tutorial/coordinates
la source
Pour obtenir le décalage total d'un élément, vous pouvez résumer récursivement tous les décalages parents:
avec cette fonction d'utilité, le décalage supérieur total d'un élément dom est:
la source
Merci ThinkingStiff pour la réponse , ce n'est qu'une autre version de celui-ci.
la source
J'ai utilisé avec succès la solution d'Andy E pour positionner un modal bootstrap 2 en fonction du lien dans une ligne de tableau sur lequel un utilisateur clique. La page est une page Tapestry 5 et le javascript ci-dessous est importé dans la classe de page java.
javascript:
}
Mon code modal:
Le lien dans la boucle:
Et le code java dans la classe de page:
J'espère que cela aide quelqu'un, ce message a aidé.
la source
Après de nombreuses recherches et tests, cela semble fonctionner
voir http://jsbin.com/xuvovalifo/edit?html,js,output
la source
Je pensais juste que je jetterais ça aussi.
Je n'ai pas pu le tester dans les anciens navigateurs, mais cela fonctionne dans le dernier du top 3. :)
la source
Étant donné que différents navigateurs affichent la bordure, le remplissage, la marge, 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 souhaitez dans une dimension précise:
Pour récupérer la position gauche, vous devez retourner:
la source
la source
el.offsetTop
etel.offsetLeft
(l'OP ne dit rien sur jQuery ... Je ne sais pas pourquoi votre réponse utilise jQuery non plus ...)