11523 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

J'aimerais que deux blocs html indépendants mis cote à côte (grâce à un float: left) possèdent la même hauteur.

Prérequis:

- La hauteur des blocs est données par le contenu de celui-ci. Autrement dit, aucune propriété height n'a été spécifiée pour ces blocs dans la feuille de style. La valeur est donc "auto".
- Le bloc le plus grand n'est pas déterminé. Tout dépend du contenu de ceux-ci et ce contenu est appelé à changer régulièrement.
- Ces deux blocs peuvent posséder des border et des padding de valeur différentes.

J'ai tenté d'utiliser la propriété offsetHeight comme ceci.

function equalizeHeight(elem1, elem2) {
	if (elem1.offsetHeight > elem2.offsetHeight) {
		elem2.style.height = (elem1.offsetHeight)+"px";
	} else {
		elem1.style.height = (elem2.offsetHeight)+"px";
	}
}


Malheureusement, il semble que offsetHeight reprenne la valeur de la hauteur, des marges internes supérieure et inférieures ainsi que des bordures supérieures et inférieures (peut-être également les marges externes).
Bref, un bloc avec une auteur de 200px, une bordure de 3px et un padding de 5 px aura un offsetHeight = 216px (200 + 3 + 3 + 5 + 5)

Dans cet exemple, j'assigne donc 216px au style.height au lieu de 200px;

Est-ce que l'un de vous pourrait m'aider à régler ce problème ?
Y a -t-il un meilleur moyen que offsetHeight pour déterminer la hauteur d'un bloc ?
Comment connaitre la valeur des padding et des borders ?

Merci
Modifié par Mathieu_vd (25 Mar 2007 - 09:15)
Salut,

Ma réponse va te paraître peu constructive, mais je pense que tu te compliques beaucoup la vie.

A mon avis, il est bien plus intéressant d'essayer de trouver une solution HTML+CSS pure, éventuellement à base de tableaux : elle fonctionnera aussi si JS n'est pas disponible, sera bien plus robuste, plus lisible et prendra en compte les cas de mise à jour de l'affichage (redimensionnement de la fenêtre, modification de l'arbre DOM, ...).
Merci pour ta réponse.

J'ai tenté de trouver une solution CSS mais je ne suis pas arrivé à trouver quelque chose qui fonctionne aussi sous IE. Le fait d'utiliser un tableau ne me paraît pas envisageable vu que mon projet consiste justement à éléminer les tableaux d'une page existante. Je garde donc l'usage de cette balise comme dernier recours.
Cette égalisation des hauteurs n'est qu'un fignolage graphique (mais indispensable). Si le JS n'est pas supporté, le surfer obtiendrait deux blocs de hauteurs différentes mais au contenu accessible. Le non support du js n'est donc pas un problème dans ce cas-ci.

Bref, l'usage d'un tableau serait effectivement plus simple mais n'est pas souhaitable car je perdrais les avantages du positionnement CSS pour une histoire d'ajustement de hauteur.
Cela dit, ton avis est très pertinent et je serai peut-être contraint d'agir de la sorte.
Oui Merci.

Cela aurait pu m'aider si c'était toujours le même bloc qui était le plus grand.
Or ce n'est pas le cas.
Je vais le préciser dans l'énoncé du problème pour que ce soit bien clair.
Tu peux tout a fait trouver une solution pure css.
Il faut que tu mettes tes deux bloc flottant dans un bloc plus grand auquel tu attriburas la propriété overflow auto ET height:1% pour ie ainsi il engloberat systématiquement le plus grand des deux flottants. A ce même bloc tu lui mettras les deux backgrounds ou du moins la partie basse (ceci dépend de ton design).
Montre nous une copie d'écran du resultat que tu veux obtenir si tu veux plus de précision, mais je suis presque sur qu'il ne devrais pas y avoir de problémes.
Il faut vraiment éviter, sauf cas trés spéciaux de faire du positionnment avec javascript, c'est beaucoup plus long à développer et trés vite source de probléme.
Modifié par matmat (22 Mar 2007 - 16:22)
Je suis en train de tenter de revenir vers une méthode CSS.
Je l'avais écartée pour éviter de recourir à des images pour simulé les border.
Mais je ne suis pas certains que ce soit pire que de recourir au JS.

Mon idée était:
CSS positionne et décore les blocs.
Ensuite une couche de domScripting optionnel, leur donne la même hauteur pour une finition graphique.

Mais je pensais que le côté JS serait plus évidant à mettre en place.

Merci pour votre aide.
Je vous tiens au courrant.
Modifié par Mathieu_vd (22 Mar 2007 - 16:42)
Ok, je comprend mieux ton probléme, effectivement faire des cadres en utilisant le background du bloc contenant c'est un peu tordu comme méthode. De plus il faut que ça corresponde avec les borders des tes blocs...

En js ce que tu peux faire c'est donner la valeur non pas de ton bloc le plus grand mais du bloc contenant (en overflow hidden ou auto et height:1% pour ie). Ce devrait marcher
J'ai donc appliqué la méthode dont parlais matmat en attendant de trouver un éventuel autre moyen. (plus d'info)
Cela m'ennuie de devoir utiliser deux images juste pour cela.
En plus, si je veux modifier la couleur de la bordure, je devrai modifier les deux images... mais bon.

Voici une exemple simplifié de ce que cela donne.
upload/6470-exemple.gif

Je ne ferme pas le sujet tout de suite au cas où quelqu'un aurait une autre proposition.

matmat a écrit :
En js ce que tu peux faire c'est donner la valeur non pas de ton bloc le plus grand mais du bloc contenant (en overflow hidden ou auto et height:1% pour ie). Ce devrait marcher


Merci pour cette proposition mais je ne la comprends pas bien.
Modifié par Mathieu_vd (22 Mar 2007 - 17:59)
L'idée c'est de mettre tes trois blocs dans un bloc qui les contients, a ce bloc tu lui met un contexte de formatage (overflow ou float), donc il prendra la valeur de ton plus grand bloc. Ensuite avec offsetHeight et un id tu récupére la hauteur de ce bloc. Puis tu fais une boucle qui selectionne toute les div a l'intérieur de ta div globale et pour chacune tu mets la hauteur récupérée par le offsetHeight.

Ce code par exemple:

function egalizeHeight(){
  var divGlobal = document.getElementById('div_global');
  heightDiv = divGlobal.offsetHeight;
  var div = divGlobal.getElementsByTagName('div');
  for (var I=0; I<div.length; I++) {
    div[I].style.height = heightDiv +'px';
  }
}

avec comme css:
#div_global{
	overflow:hidden;
        height:1% (atention a mettre dans des comentaires conditionnel pour ie)
}

#div_global div{
	float:left;
	width:200px;
	border:2px solid red;
	margin-left:10px;
	padding:10px;
}


devrais fonctionner
Modifié par matmat (22 Mar 2007 - 18:26)
A oui en effet, c'est une très bonne idée.

Je testerai dès que j'aurai le temps.

Sinon quelle est la méthode préférable dans ce cas ?
Celle qui recoure au JS ou celle qui utilise uniquement le CSS et deux images ?
Je ne sait ça dépent d'un ensemble large de facteurs.
Effectivement si tu es obligé de changer le design réguliérement c'est pas trés souple les images pour faire des bords.
Par contre si tu peux modifier le design et par exemple mettre des fonds c'est peut-être mieux.
D'un autre coté si ce ne pose aucun probléme que si js desactivé tes blocs ne sont pas de hauteur égales (si tout ton contenu et lisible), c'est peut-être plus simple comme ça.
Il faut voir le facteur temps, la souplesse, la lisibilité du code, l'accesibilité et faire son choix.
matmat a écrit :
Ensuite avec offsetHeight et un id tu récupére la hauteur de ce bloc. Puis tu fais une boucle qui selectionne toute les div...


C'est pas mal sauf que le problème initial demeure: la hauteur du block conteneur sera égale à la hauteur du bloc contenu + marge + padding + border.
Dans ton exemple; les bloc auront donc une hauteur trop grande de 24px.
Pour que cela soit parfais, il faudrait donc récupérer dynamiquement le padding et border des blocs et le soustraire au offsetHeight.
C'est possible mais beaucoup plus laborieux que la première idée que je me fesais de ce script donc je préfère resté à la technique CSS avec deux background-image

Merci pour vos conseils
Modifié par Mathieu_vd (25 Mar 2007 - 09:14)
Sauf que si tu sais la hauteur de tes padding tu peux l'enlever à ta hauteur récupéré par truc.style.height = machin.offsetHeight-20+'px'.
Si ton padding change tout le temps, tu peux aussi le mettre dans une div imbriqué dans celle a quelle tu apliques ta hauteur, comme ça tu es sur de n'avoir aucun probléme Smiley cligne .

Enfin comme je te disais le mieux c'est de faire ce qui te semble le plus simple
Modifié par matmat (25 Mar 2007 - 23:39)