Niveau Niveau confirmé

Display inline-block, une valeur trop peu utilisée

Articlecss

Publié par le , mis à jour le (637940 lectures)

block inline css positionnement display

Floatera, floatera pas… mais pourquoi ne pas utiliser la valeur inline-block de la propriété display en CSS ?

Vous connaissez certainement les valeurs block ou inline, mais moins celle de inline-block et pourtant elle peut vous servir dans bien des cas.

Voyons dans quelles conditions nous pouvons l'utiliser (de manière non exhaustive) dans un premier temps, puis dans un second temps quelques difficultés dans son utilisation.

Cette astuce a été publiée initialement sur le blog personnel de l'auteur, creativejuiz.fr à la date du Jeudi 17 mars 2011.

Utiliser display: inline-block

Par défaut les éléments input ont comme valeur de display celle de inline-block. C'est pour cela que l'utilisation de ces éléments HTML sont simples : ils restent à côté de votre label associé, et vous pouvez en changer sa largeur, sa hauteur, ses marges, son alignement vertical, etc.

Le formulaire

Quelle transition ! « Bon allez, c'est juste pour le formulaire, je vais utiliser un tableau de mise en page pour ne pas m'embêter ».
Je le lis et le vois encore souvent dans les codes sources (et je l'eus fait), et même récemment sur un site communal d'une ville du grand Est.
Si ce n'est pas du tableau ce sera un jeu de float et de clear.

Je vous propose cette forme de mise en page pour formulaire.

Dans cette mise en page les label passent d'un display à valeur inline à un display: inline-block;
Un élément en inline-block peut recevoir une valeur de vertical-align qui, par défaut, ne semble pas être la même sur IE et sur les autres navigateurs.

Notre code CSS va donc nous permettre d'avoir un comportement homogène.
Le HTML :

<form name="my_form" action="#result" method="post">
	<p> <label for="nom">Nom</label> <input type="text" id="nom"> </p>
	<p> <label for="email">E-mail</label> <input type="e-mail" id="email"> </p>
	<p> <label for="sujet">Sujet</label> <input type="text" id="sujet"> </p>
	<p> <label for="message">Message</label> <textarea id="message"></textarea> </p>
</form>

La CSS :

input, textarea {
	/*déjà en inline-block*/
	width: 150px;
	padding: 4px;
	vertical-align: top;
}
#sujet { width: 250px; }
textarea {
	width: 300px;
	height: 5em;
}
label {
	display: inline-block;
	width: 100px;
	margin-right: 20px;
	vertical-align: top;
	text-align: right;
}

Aperçu du formulaire

Une navigation horizontale (éléments de liste)

Le deuxième cas où l'on peut remplacer aisément le float par du inline-block c'est celui d'une liste dont on souhaite dimensionner les liens placés sur une seule ligne.
La valeur par défaut d'un <li> pour la propriété display est list-item. Cette valeur est connue pour ses styles par défaut (margin-start plus ou moins élevée, puce de liste de type disc, saut de ligne, etc.).

Cette valeur par défaut du display va nous poser problème si on veut placer tous nos liens sur une seule ligne.
Qu'à cela ne tienne, il nous suffit d'appliquer la valeur inline à la propriété display :

Le code HTML :

<ul>
	<li><a href="#">Item 1</a></li>
	<li><a href="#">Item 2</a></li>
	<li><a href="#">Item 3</a></li>
	<li><a href="#">Item 4</a></li>
</ul>

Le code CSS :

li {
	display: inline;
	list-style: none; /* pour enlever les puces sur IE7 */
	margin: 10px;
}

Ce tronçon est plutôt simple, mais il a le mérite de supprimer les styles par défaut de notre liste.

Remarque : la valeur inline sur le li est suffisante dans mon exemple. Pour des styles plus complexes, il est possible d'utiliser la valeur inline-block, mais celle-ci va poser des problèmes, précisés plus loin dans cet article.

Les liens sont un peu collés si on en reste là, on va donc leur appliquer de nouveaux styles :

li a {
	display: inline-block;
	width: 100px;
	padding: 5px 10px;
	text-decoration: none;
	color: #fff;
	font-weight: bold;
	background: #999;
} 

Aperçu

Le lien ainsi stylé peut subir autant de transformations que vous le désirez, lui appliquer un background et lui donner les dimensions que vous souhaitez devient un jeu d'enfant.

Quelques soucis…

Oui il y en a, sinon ça ne serait pas marrant !

Le cas Internet Explorer

En effet lorsque l'on souhaite appliquer un inline-block sur un élément, la valeur est prise en compte par IE uniquement si celle par défaut de l'élément est inline.
Pour les cas précédents, nous avions un <label> à placer en inline-block, ceci n'a pas posé de problème car la valeur par défaut de son display est inline (idem pour l'élément <a>).
Dans l'exemple suivant nos éléments sont par défaut en block. Le remplacement de cette valeur par inline-block ne sera pas compris par IE (version inférieure à 8).

Mais il y a une astuce.
Sur une feuille de style alternative (code à placer entre les balises <head>) :

<!--[if lte IE 7]>
<link rel="stylesheet" type="text/css" href="styles-ie7.css" />
<![endif]-->

il vous faudra préciser (dans votre CSS) :

element { 
   zoom: 1; /*offre le layout à un élément (*)*/
   display: inline;
}

(*) Pour IE un élément inline qui possède le Layout aura le même comportement qu'un inline-block.

Le problème white-space

Venons-en à l'exemple.
Pour une raison qui ne nous intéresse pas, je souhaite afficher trois divisions les unes à côté des autres, je sais que la place disponible en largeur est de 900px :

<div class="container">
	<div><p>Lorem Elsass ipsum bredele [...]</p></div>
	<div><p>Lorem Elsass ipsum bredele [...]</p></div>
	<div><p>Lorem Elsass ipsum bredele [...]</p></div>
</div>

En utilisant ce code CSS je devrais pouvoir afficher mes éléments les uns à côté des autres :

.container {
	width: 900px;
}
.container div {
	display: inline-block;
	width: 300px;
}

En effet chaque div fait normalement 300px de largeur, comme nous en avons trois nous rentrons précisément dans les 900px du conteneur.
Sauf que l'indentation de notre code fait apparaître un espace blanc (white-space) d'environ 3/4px entre chaque élément.

Une des solutions est de ne plus indenter la partie du code concernée. Cela vous obligerait à accepter de ne plus « aérer » certaines parties de votre code... pas super pour la lisibilité. Cependant ça ne pose pas de problème si vous effectuez une minification de votre code HTML en fin de projet ou côté serveur.

Une autre solution consiste en l'utilisation de commentaires HTML, de cette manière :

<div class="container exemple"><!--
	--><div><p>Lorem Elsass ipsum bredele [...]</p></div><!--
	--><div><p>Lorem Elsass ipsum bredele [...]</p></div><!--
	--><div><p>Lorem Elsass ipsum bredele [...]</p></div><!--
--></div> 

Pas super pratique, surtout si pour le code généré vous n'avez pas entièrement la main dessus (plugins ou fonctions WordPress, ou pas envie de tout modifier).

La dernière solution est de passer par du CSS.
Il nous faut « supprimer » le white-space entre les div.

Voici une discussion intéressante apportée par Raphaël : display-inline: block; et espaces indésirables, il s'agit de la simple annulation de la valeur font-size sur le parent qui est intéressante. Elle a pour effet de supprimer les espaces indésirables, mais vous oblige à utiliser une valeur de corps en pixels pour les enfants tant que le navigateur ne reconnaît pas l'unité fluide "rem".

Alignement vertical

Une fois ce travail d'alignement effectué, il arrivera probablement que le contenu ne soit pas aligné à la verticale comme vous le souhaitez.
Pour cela je vous rappelle que nous avons la propriété CSS : vertical-align.
Souvent bien pratique de choisir la valeur top pour placer les éléments en haut de leur conteneur, il vous arrivera probablement de devoir aligner les éléments entre eux de manière centrée (middle) ou tout en bas du conteneur (bottom). (voir les autres valeurs de vertical-align)

Petit exemple pour la route

Merci pour votre lecture. N'hésitez pas si vous avez des exemples ou des contre-exemples d'utilisation.

Liens utiles

Commentaires

Je l'utilise depuis quelques temps et elle est vraiment très utile en utilisant les avantages des block et des inline :)
En tout cas, très bon article

Très vrai le clear both est souvent utilisé, mais des fois il est aussi couplé à du display inline- block, dans les cas où les balises <span></span> sont utilisées en tant que pseudo block
il n est donc pas rare non plus d'avoir :
<style type="text/css">
#exemple1{ display:inline-block;
float:left;
}
#exemple2{ display:inline-block;
float:right;
}
</style>
<div>
<span id="exemple1">exemple1<span>
<span id="exemple2">exemple2<span>
<div style="clear:both;"></div>
</div>

@wrb3os : en fait les spécifications CSS définissent une priorité lorsque des schémas de positionnements via position absolute, float et display sont appliqués en même temps.
Si tel est le cas, float écrasera systématiquement la propriété display. En clair, dans tes exemples, la propriété display est purement et simplement ignorée, donc inutile.
C'est via la propriété float que tu parviens à dimensionner tes éléments. Bref, c'est l'inverse de l'objectif de cet article, dont le but est d'expliquer comment se passer de float et des positionnements hors-flux, forcément problématiques (débordements, clear, etc.)

Perso, je l'utilise de plus en plus cette propriété, elle m'a déjà sorti de problèmes bien épineux. Un très bon rappel !

Le CSS est tellement simple parfois. J'utilise depuis plus d'un an grâce à Alsacréations et c'est tout simplement indispensable. Bien moins galère que ces "float" moches :D
Il y a le display:table-cell qui est bien pratique aussi et qui commencent à bien être intégrer. A suivre aussi cette propriété.

Cet article tombe à pic, je cherchais à l'utiliser hier et IE me cassait les pieds... je vais refaire un essaie avec les infos données. Merci

Chouette rappel, pour ma part j'ai toujours utilisé l'inline-block, le float étant tellement barbare.
Mais bon depuis la Kiwi et le livre de Raphael, j'opte pour le rendu de tableau en CSS vu que les deux ne sont reconnu qu'a partir de IE8 (sauf erreur de ma part)

Pour appuyer ce que vient de dire Gili.

La solution qui résout tous les cas de figures présentés ici est l"usage de display:table-cell; qui a l'avantage d'apporter un comportement d'affichage identique à un tableau. De fait, les éléments s'adaptent tous à la même hauteur et il n'y a pas le problème de l'espace blanc.

En revanche, comme pour toute solution idéale, IE ne comprend cette directive qu'à partir de IE8...

Depuis le temps et grâce à Alsa', je n'utilise plus le méchant "float" partout; il reste quand même très utile dans le cas d'une mise en page "responsive/réactive".
Cependant, je vais m'empresser de retourner dans tous les sens la propriété "display:table-cell".

[troll inside] Arrêter de vous préoccuper d'IE, on s'en fiche ! [/troll]

Suggestion "citation best-of" : " Elle est pas bonne ma width ! "

Merci pour l'article bien pratique et bien expliqué (comme d'hab ;-) )
Je n'utilisais pas l'inline-block pour les projets ayant une forte visibilité sur IE jusqu'a présent ; merci pour l'astuce avec le zoom:1 ;)

@jose2204 : nos exemples ne proposent pas de fallback pour les versions antérieures à IE8. Mais la solution "zoom: 1" + "display: inline" sur une feuille de styles alternatives pour ces versions fonctionnent parfaitement :)
Si tu veux un exemple, sur mon site http://jq.creativejuiz.fr/ quasiment tous les blocs de la homepage sont en inline-block, une feuille alternative (css/lte8.css) est chargée pour IE7 et IE6.

@denisdeejay : c'est toujours un plaisir ;)

Bonjour,

plutôt que de perdre du temps à chercher tout seul, je viens solliciter de l'assistance chez les spécialistes.

J'utilise un modèle de site (responsive) trouvé sur le net qui me donne jusqu'ici toute satisfaction.

La page-type est constituée de trois colonnes : menu / content / adv (pub), qui sont toutes calées en haut d'écran.

le site est à l'adresse : https://nivoyousnisoumis.re/ (ce n'est PAS contagieux!! lol)

Chaque colonne est définie dans la page .css avec un "layout" qui contient la ligne "display : inline-block" et elles sont toutes alignées en haut d'écran.

J'aimerais pouvoir inclure un 4e bloc "titre" qui serait placé dans la colonne centrale mais serait fixe et ne disparaîtrait pas quand on déroule la colonne "content" avec la souris. J'ai essayé avec un simple "div" en utilisant les propriétés "fixed" ou "absolute" mais sans trouver la solution...

Merci d'avance

le Dodo Volant ;-)