Centrer un float en CSS
Par cgo2, mardi 23 ao�t 2005 à 21:32 :: Les standards du web :: #46 :: rss
align="center"
, et le contenu est un tableau d'une seule ligne dont le nombre de cellules varie de 1 � 5 (le nombre maximum de boites pour tenir sur une seule ligne). Mais comment faire �a en CSS ?
Probl�matique
L'effet recherch� ressemble � �a :
Ma premi�re id�e, pour placer les bo�tes est d'utiliser le positionnement float avec un hr
et la propri�t� clear : both;
comme expliqu� dans ce tr�s bon article sur OpenWeb.
Au niveau code �a donne :
<div class="galerie"> <div class="bo�te">bo�te 1</div> <div class="bo�te">bo�te 2</div> <div class="bo�te">bo�te 3</div> <div class="bo�te">bo�te 4</div> <div class="bo�te">bo�te 5</div> <hr class="clear" /> </div>
Appliquons le style suivant :
.galerie { background : #ccc; width : 360px; /* (50 + (5 * 2) + 10) * 5 + 10 */ } .bo�te { background : #69c; float : left; margin : 10px 0 10px 10px; padding : 5px; width : 50px; text-align : center; } .clear { clear : both; visibility : hidden; }
Ça donne :
Avec 3 bo�tes uniquement :
Vous pouvez tester ce premier exemple.
Le positionnement est celui recherch� lorsque toutes les bo�tes sont pr�sentes, mais, malheureusement, d�s qu'il manque des bo�tes, celles restantes sont cal�es � gauche. C'est tout � fait logique puisqu'elles sont flottantes � gauche, mais ce n'est pas ce que nous voulons !
Un deuxi�me conteneur pour le centrage
Au d�part, j'ai simplement essay� quelques techniques de centrage css appliqu�es sur les fiches ou sur le conteneur. Mais rien de tout �a ne fonctionne.
Le probl�me est qu'on ne peut pas centrer un flottant, � cause de sa conception m�me. Comme �crit tr�s justement dans l'article d'Openweb : Une bo�te flottante est retir�e du flux normal, et plac�e le plus � droite (float: right) ou le plus � gauche (float: left) possible dans son conteneur.
Il est donc logique que les techniques de centrage ne puisse pas s'appliquer (centrer par rapport � quoi, puisque la bo�te est retir�e du flux ?).
Par contre, un �l�ment non-flottant peut, lui, �tre centr� (par exemple avec la technique des marges auto
). Imaginons que l'on cr�e un autre conteneur, qui soit centr� par rapport au premier (la galerie), et qui contienne les fiches...
Au niveau code �a donne :
<div class="galerie"> <div class="conteneur"> <div class="bo�te">bo�te 1</div> <div class="bo�te">bo�te 2</div> <div class="bo�te">bo�te 3</div> <div class="bo�te">bo�te 4</div> <div class="bo�te">bo�te 5</div> <hr class="clear" /> </div> </div>
On applique le m�me style que pr�c�demment. Mais il faut rajouter de quoi centrer le conteneur :
.galerie { text-align : center; /* uniquement pour IE */ } .conteneur { margin : 0 auto; }
L� se pose un probl�me - LE probl�me devrais-je dire - : pour que �a fonctionne il faut que le conteneur enveloppe parfaitement les bo�tes, et donc soit exactement � la bonne taille. La formule donnant la taille est facile � trouver :
taille = nombre de bo�tes * ( width + padding + margin-left ) + margin-right
Mais je n'ai strictement aucune id�e de comment faire �a en CSS. C'est th�oriquement possible de le fixer dans un style inline (dans la page) appliqu� au moment o� le script qui g�n�re la page affiche les bo�tes. Une autre solution est d'utiliser DOM pour manipuler en Javascript les styles de la page.
Impl�mentation en Javascript/DOM
Le script doit se charger de calculer la taille en fonction du nombre d'�l�ments contenus. Pour �a il faut :
- Trouver le conteneur � agrandir ; on utilisera la m�thode
getElementsById
- Compter le nombre de bo�tes contenues :
- Trouver les �l�ments
div
avec la m�thodegetElementsByTagName
- Eliminer ceux qui ne sont pas directement fils du conteneur (si les bo�tes contiennent d'autres divs par exemple
- Trouver les �l�ments
- Calculer la taille et agrandir le conteneur
Mon impl�mentation (qui n'est s�rement pas optimale) :
<script type="text/javascript"> // <![CDATA[ function setContainerSize(truc) { var navroot = document.getElementById(truc); if ( navroot ) { var lis = navroot.getElementsByTagName("div"); /* XXX : y a-t-il un moyen plus simple de ne d�tecter que les divs de rang 1 ? * ou, d�tecter selon une classe ? */ var ok = 0; var nok = 0; for ( i = 0; i < lis.length; i++ ) { if ( lis[i].parentNode != navroot ) nok++; else ok++; } navroot.style.width = ok * 70 + 10 + 'px'; } } // ]]> </script>
Maintenant, pour utiliser cette fonction, on effectue les modifications suivantes :
<body onload="setContainerSize('c1');"> ... <div class="conteneur" id="c1">
Ça donne :
Vous pouvez consulter cet exemple.
Limites et pistes de reflexions
Cette m�thode a �t� test�e avec succ�s sur IE 6, Firefox 1.x, Safari 1.3 et Camino 0.9.
Une limitation principale de cette m�thode est l'impossibilit� de centrer sur plusieurs lignes. Par exemple, si la premi�re ligne contient 5 bo�tes et la deuxi�me 2, les 2 seront cal�es � gauche. Je n'ai pas vraiment cherch� comment r�soudre ce probl�me, car �a n'�tait pas mon besoin.
L'autre am�lioration possible concerne l'impl�mentation du script, et notamment la fa�on de compter les �l�ments div
qui n'est s�rement pas optimale. Il serait �galement int�ressant de pouvoir ne pas coder en dur les tailles des div dans le script, de mani�re � avoir du code r�utilisable. Mais l� �a d�passe mes connaissance en DOM :)
Enfin, �tant donn� que le centrage se fait par un script, les bo�tes ne sont pas centr�es tant que la page n'est pas compl�tement charg�e. Dans certains cas �a provoque un petit d�calage � l'�cran le temps que le chargement se termine...
Quelques liens suppl�mentaires
Merci � Scara, MrGecko et tout le chan #asw pour la relecture ;)
4 commentaires
1. Le jeudi 25 ao�t 2005 à 06:01, par Celelibi
2. Le jeudi 25 ao�t 2005 à 07:21, par Celelibi
3. Le jeudi 25 ao�t 2005 à 08:37, par cgo2
4. Le dimanche 28 ao�t 2005 à 15:54, par Clem
Ajouter un commentaire
Vous voulez lancer un d�bat ou poser des questions autour du sujet ? Dans ce cas, utilisez plut�t le forum !