Grille flexible et centrage vertical en CSS / HTML

Une fois n’est pas coutume, je vais parler un peu web.
Je reconnais d’ailleurs que je ne me suis pas trop exprimé sur ce blog.
C’est pas grave, je vais me rattraper.

Le contexte – I

Je suis actuellement en train de modifier une partie de mon site personnel. Le plus gros du travail consiste à refaire la galerie d’images. La solution en place s’appuie sur Plogger (et ce, depuis au moins 2 ans). J’ai intégré cette galerie avec mon blog WordPress via le plugin PloggerPress (que j’ai d’ailleurs retouché à l’occasion).
Cependant, Plogger me pose au moins 2 problèmes :

  • D’abord, j’ai 2 consoles d’administration : une pour le blog et une pour Plogger.
  • Et surtout, Plogger s’appuie sur la notion de dossier d’image, alors que je veux utiliser la notion de mot-clé.

La distinction n’est peut-être pas évidente à priori.
Un album, c’est un dossier d’images. Toutes les images de ce dossier sont dans le même album. A dossier différent, album différent.
Le problème que j’ai, c’est que certaines images vont dans plusieurs albums. Je dois alors dupliquer l’image et de la mettre dans chacun des dossiers. C’est nul. Du coup, je me suis mis à la recherche d’une solution qui s’appuierait sur la notion de mot clé, ou de tag.

A une image donnée, j’associe un ou plusieurs mots clés.
Le dossier où il est placé n’a pas d’importance particulière. Le contenu d’un album (virtuel), c’est l’ensemble des images qui ont été taguées avec le mot clé qui désigne l’album.
L’inconvénient de cette solution, c’est qu’il est difficile d’utiliser un fil d’Ariane. Ou disons plutôt que son utilité est discutable, puisqu’il n’y a plus de hiérarchie et que la navigation repose complètement sur les mots clés. Ainsi, on arrive sur un album, on va voir une image, cette image est associée à plusieurs mots clés, on file sur un autre tag, d’autres images, etc…

Dans tous les cas, c’est quelque chose que Plogger ne supporte pas et il ne le supportera pas sans des changements importants.

Le contexte – II

Mon premier réflexe a été de voir ce qui existait du côté de WordPress, puisque tant qu’à changer, autant que ce soit intégré dans la console d’administration de WordPress. Il y a plusieurs plugins pour gérer des galeries d’images dans WordPress. J’en ai testés plusieurs, mais aucun ne fait vraiment ce que j’attends. Je me suis donc rabattu sur les galeries PHP externes. J’avais crû trouver un bon candidat avec Piwigo. Malheureusement, l’intégration avec WordPress est peu mâture et j’y ai vu quelques contraintes (…).

Enfin, le plus à portée de main aurait été d’utiliser un service internet pour héberger mes images, comme FlickR.
L’intérêt, c’était la visibilité et l’aspect communautaire. Le truc, c’est que j’ai beaucoup d’images et :

  • Je n’ai pas envie de payer un abonnement indéfiniment pour que mes images restent en ligne.
  • J’aime bien conserver un certain contrôle sur ce que je mets et ce que j’ai en ligne. Je n’ai pas complètement confiance en ces hébergeurs. De la même façon que je n’ai pas trop confiance dans Google Analytics et de ce qu’il ferait de mes données. Mais ça, c’est une autre histoire…
  • Enfin, j’ai envie que ma galerie soit associée à mon site.

J’ai donc renoncé à cette solution.
Et après une longue hésitation (vraiment), je me suis résolu à développer mon propre système de galerie d’image, complètement intégré dans WordPress.
L’accent est mis sur la simplicité, les albums définis par des tags et sur le référencement de mes images par les moteurs de recherche. J’ai quasiment terminé ce plugin. Il me reste quelques petites choses à nettoyer, mais ce n’est pas trop mal, y compris l’intégration avec des thèmes. Il suffit de créer un template gallery.php (ou vous l’appelez comme vous voulez) dans votre thème, et vous pouvez utiliser la galerie.

J’en suis assez content.
Mais je reconnais que je ne sais pas encore si je vais le verser dans la communauté. J’ai assez d’expérience dans l’open source pour savoir que les projets avec une communauté active sont assez rares. La plupart du temps, il y a 1 ou 2 contributeurs, et bien souvent, ce sont ceux qui ont proposé le projet. Si je le contribue, je m’attends donc à devoir assurer le support seul et sur mon temps libre.

Le problème

Je pense déjà à la tête de ceux qui seront arrivés sur cet article en cherchant une solution et qui seront tombés sur un roman. Toutes mes excuses.
Dans ma galerie, j’affiche les images sous la forme d’une grille. Et parce que mon thème a une largeur flexible, je n’ai pas envie de restreindre le nombre de colonnes. Si j’ai la place pour afficher 4 colonnes côte à côte, faisons-le. Si je n’ai de la place que pour 2 colonnes, et que j’en ai 4 à afficher, et bien j’afficherai les 2 premières colonnes côté à côté, et les 2 autres en-dessous.

Jusque-là, pas de problème, des div avec un positionnement flottant font l’affaire.
Là où ça se corse, c’est quand on veut centrer horizontalement ET verticalement le contenu de chaque div.
En effet, dans la galerie, il y a des images de taille différente. Les aperçus ont certes tous la même largeur, mais la hauteur peut varier. Après avoir testé, j’ai trouvé que le plus élégant était de centrer les images. C’est frappant quand le nombre de colonnes augmente. En occupant l’espace de manière aussi régulière que possible, le rendu est bien meilleur.

J’ai essayé d’illustrer ce qui se passe par défaut et ce qui se passe quand on centre tout.

Alignement par défaut, en bas

Alignement par défaut, en bas

Centrage total

Centrage total

Mais comment faire ça tout en conservant un nombre de colonnes qui s’adapte à la largeur du conteneur ?

Les solutions

Première idée : Javascript.
On implémente une fonction qui va nous afficher une table et cette table sera peuplée dynamiquement en fonction de la résolution de l’écran et de la taille du conteneur. L’intérêt de la table, c’est de pouvoir utiliser la propriété CSS vertical-align.
Cependant, on a beau être à l’heure d’Ajax, je suis toujours réticent à baser mon design sur du Javascript. En général, je fournis un rendu par défaut, et si Javascript est activé, et bien je peux me permettre d’améliorer cet rendu. Cependant, pour ma table dynamique, j’ai été un peu fainéant et j’ai exclu cette solution.

Deuxième idée : appliquer la propriété CSS display=table-cell sur nos conteneurs d’image.
Encore une fois, l’intérêt, c’est de pouvoir utiliser la propriété CSS vertical-align.
Malheureusement, IE 7 ne supporte pas cette propriété, et les statistiques de mon site me disent qu’il y a encore des visiteurs qui l’utilisent. Je vais attendre un peu avant de passer sur cette solution et de mettre un message pour leur dire de changer de navigateur. Quelque chose dans le genre de IE6 no more.

Troisième idée : faire le bourrin.
C’est la solution qui gênera sans doute les puristes. Lorsque j’ai découvert CSS, cela fera bientôt 7 ans, les premiers articles sur lesquels je suis tombé présentaient CSS comme la solution pour faire de jolies mises en pages sans tableaux.
Avec cette solution, on repart donc sur des div flottants, qui vont adapter le nombre de colonnes à la largeur de la page, et on place une table dans chacun de ces div.
On peut alors utiliser vetical-align sur les cellules de la table. Cela marche, et cela a l’air de passer sous IE 7.

Voilà donc un peu de code pour cette dernière solution.

Côté CSS…

.img-container {
	float: left;
	margin-bottom: 18px;
}

.img-container img {
	margin: auto;
}

table {
	border-spacing: 5px 0px;
}

td.photo {
	height: 320px;
	width: 340px;
	padding: 0 14px 0 14px;
	vertical-align: middle;
	text-align: center;
}

td.title {
	text-align: center;
	border: solid 1px white;
	height: 35px;
	font-size: 14px;
}

Côté HTML.

<div class="img-container">
 <table>
   <tr><td class="photo">
       <a href="#"><img src="#" title="..." alt="..." /></a>
   </td></tr>

   <tr><td class="title">
       <a href="#">Texte</a> &nbsp; <strong>( 1 )</strong>
   </td></tr>
 </table>
</div>

<div class="img-container">
 <table>
    <tr><td class="photo">
       <a href="#"><img src="#" title="..." alt="..." /></a>
    </td></tr>

    <tr><td class="title">
        <a href="#">Texte</a> &nbsp; <strong>( 1 )</strong>
    </td></tr>
 </table>
</div>

<div style="clear: left;";></div>

Voilà un petit aperçu du rendu dans la galerie.
En pleine résolution…

La galerie en pleine résolution

La galerie en pleine résolution

Et quand je redimensionne ma fenêtre…
Les colonnes qui ne rentrent pas vont à la suite grâce aux div flottants. Et les tables me garantissent un centrage parfait.

La galerie s'adapte au redimmensionnement

La galerie s’adapte au redimmensionnement

Publicités

About this entry