La valeur inline-block
de la propriété display
est à la mode, même si elle demeure encore trop peu connue et mal utilisée. Elle offre de multiples avantages dont le principal est de pouvoir disposer des éléments les uns à côté des autres, tout en étant dimensionnés et sans les retirer du flux.
L'un de ses inconvénients majeurs est l'apparition d'un espace indésirable et incompressible de prime abord entre les blocs. S'il n'est pas gênant, tant-mieux; sinon, de multiples techniques plus biscornues les unes que les autres existent.
Le cas «white-space»
Comme tous les éléments de type inline ou de contenu textuel, les objets munis de la déclaration display: inline-block respectent la règle des caractères blancs (whitespace), c’est-à-dire que n’importe quel caractère espaçant deux éléments inline-block va immanquablement apparaître entre leurs deux boîtes. Chaque caractère «espace», «tabulation», «nouvelle ligne», «retour chariot» ou «nouvelle page» peut tenir lieu de white-space et séparer les blocs visuellement.
L’espace créé par le white-space
est de l’ordre de 4 pixels, mais cela varie selon les navigateurs et la taille de police.
Dans la grande majorité des cas, cette situation n’est guère gênante. Cependant, elle peut le devenir si votre présentation doit être calée au pixel près, par exemple pour un parent de 600 pixels de large devant contenir trois paragraphes de 200 pixels chacun :
#main {
width: 600px
}
#main p {
display: inline-block;
width: 200px;
}
De nombreux concepteurs se sont penchés sur cette problématique, certains tentent de jouer avec les marges négatives, d’autres sur l’espace entre lettres (letter-spacing
). Mais à l’heure actuelle, aucune solution ultime n’a été publiée.
text-space-collapse
La solution idéale est sans aucun doute en pleine élaboration dans les laboratoires du W3C et se nommera peut-être text-space-collapse
(précédemment connue sous le nom de white-space-collapse
).
Elle n'a a priori qu'un seul défaut à l'heure actuelle : elle n'est encore reconnue par aucun navigateur. Passons donc aux autres solutions...
Modification du code HTML
La première alternative et la plus logique consiste à supprimer les white-space physiquement et directement au sein du code HTML. Cela peut se faire en «collant» les éléments les uns aux autres :
<div>
<p>Lorem Elsass ipsum</p><p>réchime amet sed bissame so libero knackes choucroute</p><p>Hopla kuglopf flammekueche</p>
</div>
Variante : commentaires HTML
On peut encore transformer les white-spaces en commentaires HTML, qui ne seront pas interprétés par les navigateurs mais préserveront visuellement les retours à la ligne, ce qui facilitera la lecture du code par un intégrateur :
</p><!--
--><p>
Ce qui donne au final :
<div>
<p>Lorem Elsass ipsum</p><!-- whitespace
--><p>réchime amet sed bissame so libero knackes choucroute…</p><!-- whitespace
--><p>Hopla kuglopf flammekueche</p>
</div>
Cette alternative, bien que parfois un peu «inesthétique» et nécessitant d'avoir accès aux fichiers HTML, se révèle sans aucun doute la plus robuste et la plus pérenne actuellement.
Solutions CSS pures
Via CSS, il existe également certaines techniques permettant de contourner cet espacement non souhaité.
Aucune des méthodes décrites ci-dessous ne sera parfaite, je préfère vous l'annoncer sans détour, mais elles ont un avantage indéniable également : celui de corriger le problème sans avoir à toucher à la structure HTML, et en employant la technologie adaptée, à savoir CSS.
white-space: nowrap et overflow: hidden
La propriété white-space: nowrap
interdit les césures sur les espaces et autres caractères blancs, elle évite par conséquent le retour à la ligne des éléments inline-block
, ce qui aura pour conséquence de déborder visuellement de leur parent. Pour masquer ce débordement, il peut être judicieux d'employer overflow: hidden
sur le parent :
#main {
width: 800px;
overflow: hidden;
white-space: nowrap;
}
#main p {
display: inline-block;
white-space: normal;
width: 200px;
}
Cette proposition ne constitue qu'une pseudo-solution car elle ne fait que masquer le problème sans le résoudre : l'espace est toujours présent mais les blocs demeurent sur la même ligne.
letter-spacing négatif
Le white-space étant un caractère blanc, il est possible de l'atténuer ou de le supprimer en jouant que la propriété letter-spacing
(espacement des caractères) du parent, puis de rétablir l'espace normal au sein des enfants.
Le problème est que dans tous les cas, le rendu final dépendra – au minimum – de la police de caractères utilisée.
L'on côtoie fréquemment des valeurs telles que :
parent {letter-spacing: -0.25em}
enfants {letter-spacing: normal;}
Toutefois, la valeur de l’espace entre les lettres étant différente pour chaque police, cette méthode est à adapter au cas par cas :
- Verdana : -0.5em
- Arial : -0.25em
- Tahoma : -0.333em
- etc.
Dans la pratique, cela fonctionne mais demeure un peu rédhibitoire, ne trouvez-vous pas ?
margin-right négatif
Une autre solution consiste à appliquer une marge externe droite négative à chacun des blocs enfants afin de « tracter » son successeur direct. La valeur de cette marge, après tests empiriques, a été estimée à 0,25 em, mais cela peut varier selon la fonte choisie :
chaque_enfant {margin-right: -0.3em;}
Cette technique, pour avoir été vérifiée sur un grand nombre de navigateurs, fonctionne de manière assez universelle, mais demeure empirique et peut être considérée comme un hack puisque rien n’assure sa pérennité.
font-size : 0 sur le parent
Une dernière solution consiste à appliquer une taille de police nulle au parent, puis à redéfinir la taille de police au sein de chacun des blocs.
L’unité appropriée sera forcément non relative (pixels par exemple) puisqu’une unité fluide telle que em
, exprimée par rapport à l’unité parente, sera inopérante puisque égale à zéro :
parent {font-size: 0;}
chaque_enfant {font-size: 14px;}
Ce qui donne au final :
#main {
width: 800px;
font-size : 0;
}
#main p {
display: inline-block;
width: 200px;
font-size: 14px;
}
Cette technique, pour avoir été vérifiée sur un grand nombre de navigateurs, fonctionne de manière assez universelle (à l’exception de Safari sous Windows), mais peut poser des soucis d’accessibilité en cas de tailles de polices trop réduites du fait du choix d'unité en pixels (non agrandissables sur IE6 et IE7 dans certaines conditions) et nous oblige à employer un type d'unité non relatif.
variante : l'unité «rem»
Pour pallier au problème d'unité relatif, il est possible d'opter pour une unité introduite en CSS3 : rem
(pour «root em»).
Une taille de police en rem
n'est pas relative à la taille de police de son parent, mais à celle de la racine du document (donc l'élément <html>
en langage HTML). Bien que reconnue par une majorité des navigateurs récents (depuis IE9), il lui est aisé de proposer une alternative en pixels pour les anciens navigateurs de cette manière :
#main {
width: 800px;
font-size: 0;
}
#main p {
display: inline-block;
width: 200px;
font-size: 20px; font-size: 2rem;
}
L'intérêt principal est que la taille de police des éléments demeure fluide tel que le serait l'unité em
.
Cette alternative fonctionne plutôt bien sur Firefox, Chrome, Opera et Internet Explorer. Mais il demeure l'hypothétique souci d'accessibilité sur IE6 / IE7 décrit précédemment.
La contrainte Safari
La méthode du «font-size: 0» est séduisante mais n'est malheureusement pas supportée par un navigateur en particulier, Safari sous Windows. Celui-ci n'accepte pas les tailles de polices de valeur zéro pour des raisons d'accessibilité.
Il n'a pas forcément tort mais cela ne nous arrange pas. Ce qui change la donne est que - aussi curieux que cela puisse paraître - Safari reconnaît très bien les tailles de polices de... 1px !
Nous allons nous servir de cette possibilité, combinée à un letter-spacing: -1px
et word-spacing: -1px
(car Opera n'accepte pas de letter-spacing négatifs) pour parvenir à nos fins :
#main {
width: 800px;
font-size: 1px; letter-spacing: -1px; word-spacing: -1px;
}
#main p {
display: inline-block;
width: 200px;
font-size: 20px; font-size: 2rem; letter-spacing: normal; word-spacing: normal
}
Grâce à ce cumul de bidouilles (car il faut bien les appeler ainsi), nous obtenons le résultat souhaité sur l'ensemble des navigateurs. Bingo !
Conclusion
Ce petit et rapide tour d'horizon des différentes techniques de contournement de ce fâcheux espace indésirable introduit par la propriété inline-block
nous apprend en définitive que nous n'en sommes encore qu'à un stade de l'expérimentation et du tâtonnement.
En attendant la solution ultime émanant de CSS3 mais encore non supportée, l'ensemble des techniques CSS repose actuellement sur des hypothèses et sont fortement dépendantes de contextes précis : rien de vous assure que ces bidouilles fonctionneront partout selon les configurations de vos visiteurs. C'est donc à vous de les tester au cas par cas.
La meilleure solution, si vous en avez la possibilité, demeure finalement de supprimer physiquement l'espace au sein du HTML.