Obtenir l' offset par rapport au premier parent positionné

Contenu du snippet

Si vous utilisez element.offsetTop ou element.offsetLeft pour un élément, il n'y a pas deux navigateurs qui vous répondront la même chose.

Il semblerait que seul Firefox soit logique et renvoie l'Offset par rapport au premier parent positionné. Opera renvoie par rapport au premier parent, et IE par rapport au premier parent hiérarchique (mais malgré mes tests, je me demande encore quelle est sa définition d'un parent hiérachique...)

Le problème s'est posé pour moi quand j'ai voulu faire passer un élément d'une position statique à absolue, mais en le laissant exactement à la même position, il me fallait donc ses coordonnées par rapport au premier parent positionné. Et il m'a donc fallu écrire cette petite fonction, qui devrait renvoyer la même valeur avec tous les navigateurs.

Source / Exemple :


//donne la position par rapport à window
function getOffsetPosition(el_id, side){
	element = document.getElementById(el_id);

	newNode = document.createElement("div");
	newNode.innerHTML =  "<div style=\"height: 12px;\"></div>";
	element.insertBefore(newNode, element.firstChild);
	
	iVal = 0;
	oObj = element;
	var sType = "oObj.offset"+side;
	while (oObj && oObj.tagName != "html") {
		iVal += eval(sType);
		oObj = oObj.offsetParent;
	}
	element.removeChild(newNode);
	return iVal;
}

//donne la position par rapport au premier parent positionné
function getOffsetParentPosition(el_id, side){
	el_parent = document.getElementById(el_id).parentNode;
	while (el_parent) {
		if(navigator.appName != "Microsoft Internet Explorer"){
			if(window.getComputedStyle(el_parent,null).position == "relative" || window.getComputedStyle(el_parent,null).position == "absolute"){
				break;
			}
			else {
				if(el_parent.tagName != "HTML"){
					el_parent = el_parent.parentNode;
				}
				else {
					el_parent = null;
				}
			}
		}
		else {
			if(el_parent.currentStyle.position == "relative" || el_parent.currentStyle.position == "absolute"){
				break;
			}
			else {
				if(el_parent.tagName != "HTML"){
					el_parent = el_parent.parentNode;
				}
				else {
					el_parent = null;
				}
			}
		}
	}
	
	if(el_parent){ parentOffset = getOffsetPosition(el_parent.id, side); }
	else { parentOffset = 0; }
	return getOffsetPosition(el_id, side) - parentOffset;
}

/*
exemple d'utilisation :
<html>
<head>

<script>
	ici les 2 fonctions

	window.onload = function(){
		alert(getOffsetParentPosition("lau", "Top"));
		alert(getOffsetParentPosition("lau", "Left");
	}
</script>
</head>
<body>
	<div id="ff" style="padding-top: 65px; position: absolute;"><div id="lau"></div></div>
</body>
</html>

  • /

Conclusion :


Attention, le parent positionné doit avoir un id. Ou alors vous devrez modifier la première fonction pour qu'elle accepte aussi des éléments et pas seulement un id comme premier paramètre (c'est simple à faire :) )

Si l'élément passé à la fonction ne comporte pas d'enfants qui ont du margin-top, vous voudrez sans doute enlever le mécanisme DOM de la première fonction, cela ralentit le script.

Merci à Bultez pour son aide sur .currentStyle et getComputedStyle :)

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.