Modele de boite et quirks mode….

L’une des difficultés dans le design de composants javascript provient des différences d’interprétation du modèle de boite de la part des navigateurs. Pour faire simple, le W3C spécifie que la largeur ou la hauteur d’un élément doit correspondre à son contenu effectif. C’est à dire que les dimensions de padding, border et margins doivent être ajouter aux dimensions spécifiées. Malheureusement, Microsoft dans ces premières versions de navigateurs (jusqu’à internet explore 5) utilise un autre rendu, c’est à dire que la taille d’un élément corresponds à sa taille globale (incluant les bordures, marges….).

Vous me direz « bon c’est pas grave, ils ont corrigé le tir depuis la version 6 ». Oui mais non en raison du mode Quirks (par opposition au mode standard) qui permet au navigateur d’assurer une rétro-compatibilité en conservant l’ancien mode de calcul. Et comment est on en mode quirks (entre autre) ?

En utilisant une page HTML sans DOCTYPE autant dire dans la majorité des cas

Pour visualiser le phénomène il suffit de tester le code suivant dans une page HTML

<html>
<head>
	<title></title>
</head>
<script>
function init(){
var div=document.getElementById('div1');
div.style.width="200px";
div.style.height="100px";
div.style.border="5px solid red";
div.style.backgroundColor="blue";

var iw=document.getElementById('width');
var ih=document.getElementById('height');
var iow=document.getElementById('offwidth');
var ioh=document.getElementById('offheigth');

div.onmouseover=function(){
iw.value=this.style.width;
ih.value=this.style.height;
iow.value=this.offsetWidth;
ioh.value=this.offsetHeight;
}

div.onmouseout=function(){
iw.value="";
ih.value="";
iow.value="";
ioh.value="";
}


}
</script>
<body onload="init();">
<div id='div1'></div>
Width :<input type='text' id='width'/>
Height :<input type='text' id='height'/>
OffsetWidth :<input type='text' id='offwidth'/>
OffsetHeight :<input type='text' id='offheigth'/>
</body>
</html>

Vous observerez selon les navigateurs la différence entre la taille fixée (width et height) et la taille réellement occupée (offsetWidth et offsetHeight) en passant la souris sur la div.

Alors quelles sont les solutions:

  • introduire dans vos pages la fameuse doctype.
  • <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">
  • Utiliser des techniques de détection de navigateurs pour au besoin redimensionner les éléments

La plupart des frameworks ajax utilise la 2eme solution dans la mesure ou ils ne maîtrisent pas les pages dans lesquelles ils sont exécutés.

Attention il ne faut pas oublier de tester le mode de rendu pour affecter ou non les nouvelles tailles. Il suffit pour cela de tester la propriété document.compatMode

  • si la propriété vaut « CSS1Compat il s’agit du mode standart et on n’a pas besoin de modifier les tailles
  • si la propriété vaut « BackCompat » il s’agit du mode Quirks et il faut modifier les tailles

Ci-dessous un squelette de fonction permettant de modifier le width d’un objet

function(oHtml){
	if (window.event && document.compatMode== "BackCompat") {
	//Récuperer les border,margins et padding	
	var delta=......;	
	//MODEL IE On augmente les tailles
	oHtml.style.width =  parseInt(oHtml.style.width) + delta +"px";
	}
}

Ce probleme peut sembler anodin mais la construction de composant complexes nécessitent l’assemblage d’un grand nombre d’élément HTML et les positionnement sont très rigoureux. Des décalages de 1 ou 2px ont bien évidemment des conséquences sur la cohérence du composant.

Et voilà tout ce travail pour un bug qui date ….