title: Le petit flexbox illustré
url: http://www.vincent-valentin.name/articles/le-petit-flexbox-illustre
hash_url: fbd6c4abb662dccda9fc18f7dbd2bb14

<p><i lang="en">Flexbox</i> est un nouveau module d’affichage CSS qui apporte quelques possibilités graphiques jusqu’alors impossibles et qui permet aussi de grandement simplifier les constructions habituelles.</p>
<p>Son principal frein reste le support limité à <abbr title="Internet Explorer">IE</abbr> 10+ (pas de souci pour la majorité des autres navigateurs), mais au regard des nouveautés offertes, il est d’ores et déjà intéressant d’en comprendre le fonctionnement et de résoudre certaines problématiques grâce à celui-ci.</p>
<hr/>
<p>Déclencher un affichage <i lang="en">flexbox</i> passe par la propriété <code>display</code>.</p>
<p><i lang="en">Flexbox</i> diffère un peu des types d’affichages habituels car le changement va ici non seulement impacter l’élément sélectionné, mais également ses enfants <strong>directs</strong>.<br/>
Ainsi on parlera de <i lang="en">flex-container</i> et de <i lang="en">flex-items</i> ; et il sera possible de passer des propriétés spécifiques à ces deux composants.</p>
<p>Il sera tout à fait possible aussi qu’un élément soit à la fois un <i lang="en">flex-items</i>  et un <i lang="en">flex-container</i> : autrement dit, les imbrications <i lang="en">flexbox</i> sont possibles.</p>
<p>La courbe d’apprentissage du module peut paraître abrupte au premier abord. C’est sans compter les simplifications que permettent des outils comme <a href="https://github.com/postcss/autoprefixer"><i lang="en">autoprefixer</i></a>, qui viennent gommer les historiques de nommages et d’implémentations qui ont été faites.</p>
<p>En effet <i lang="en">flexbox</i> en est toujours au stade du brouillon et a déjà subi trois refontes. On peut néanmoins penser qu’après un travail mené depuis plus de six ans, il soit maintenant suffisamment mature ; tout comme le statut actuel (<i lang="en">last call</i>) de la spécification et le nombre très faible de tickets encore ouverts le laisse entendre.</p>
<p>Quoi qu’il en soit, au lieu de devoir écrire :</p>
<pre><code>.foo
{
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;
}</code></pre>
<p>il suffira simplement de passer par ce code pour que le post-processeur génère la même chose :</p>
<pre><code>.foo
{
    display: flex;
}</code></pre>
<p>On retrouve alors une courbe d’apprentissage relativement douce, où la principale difficulté reste le nombre de nouveautés. Nous allons donc passer en revue chacune d’elles méthodiquement, en commençant par les propriétés qui peuvent s’appliquer au <i lang="en">flex-container</i>.</p>
<hr/>
<p>Retenez cependant avant tout qu’un <i lang="en">flex-container</i> ou un <i lang="en">flex-item</i> appliquent un contexte de formatage de type <i lang="en">flex</i> équivalent au <a href="http://www.alsacreations.com/astuce/lire/1543-le-contexte-de-formatage-block-en-css.html">type <code>block</code></a>. (N’hésitez pas à lire maintenant ou plus tard l’article lié si ce concept ne vous semble pas clair.)</p>
<h2>Propriétés sur le <i lang="en">flex-container</i></h2>
<h3>La direction</h3>
<p><strong><code>flex-direction</code></strong> permet de gérer la direction, par défaut en ligne (<code>row</code>) ; on pourra aussi la passer en colonne (<code>column</code>) très facilement.</p>
<hr/>
<p>La démonstration qui suit  fait alterner différents affichages à chaque clic de votre part.<br/>
(Il en sera de même sur la plupart des démonstrations de cette page.)</p>
<hr/>


<p>On pourra également inverser les flux et utiliser <code>row-reverse</code> et <code>column-reverse</code>.</p>




<h3>Les débordements</h3>
<p><strong><code>flex-wrap</code></strong> permet de gérer les débordements des <i lang="en">flex-items</i> dans les lignes ou dans les colonnes.<br/>
Bien que par défaut ils ne soient pas autorisés (<code>nowrap</code>), il est tout à fait possible de changer ce comportement avec <code>wrap</code>.</p>


<p>On pourra même inverser le flux et les débordements avec <code>wrap-reverse</code>.</p>


<p>Notez que <code>flex-direction</code> et <code>flex-wrap</code> peuvent s’utiliser conjointement avec la propriété raccourcie <strong><code>flex-flow</code></strong>.</p>
<p>Par exemple : </p>
<pre><code>.bar
{
    flex-direction: column;
    flex-wrap: wrap;
}</code></pre>
<p>sera équivalent à :</p>
<pre><code>.bar
{
    flex-flow: column wrap;
}</code></pre>
<h3>La justification sur l’axe principal</h3>
<p><strong><code>justify-content</code></strong> aligne les <i lang="en">flex-items</i> le long de l’axe principal.</p>
<hr/>
<p>On parle d’axe principal et d’axe secondaire plutôt que d’axe vertical et horizontal car cela varie en fonction de la direction.</p>
<hr/>


<p>Par défaut les éléments sont empilés en début de flux (<code>flex-start</code>). Ils pourront l’être en fin de flux (<code>flex-end</code>), au milieu (<code>center</code>), espacés entre eux au maximum (<code>space-between</code>) ou espacés chacun d’eux par une marge identique (<code>space-around</code>).</p>
<hr/>
<p>Vous remarquerez quelques petites animations CSS qui permettent de mieux comprendre comment sont effectuées certaines répartitions d’espaces.</p>
<hr/>
<h3>La justification sur l’axe secondaire</h3>
<p>Les enfants du <i lang="en">flex container</i> sont alignés :</p>
<ul>
<li>avec <code>align-items</code> au niveau de chaque ligne ;</li>
<li>avec <code>align-content</code> au niveau de l’ensemble des lignes (il en faut donc plusieurs pour en constater l’effet).</li>
</ul>
<p><strong><code>align-items</code></strong> prend par défaut la valeur <code>stretch</code>, et accepte également <code>flex-start</code>, <code>flex-end</code>, <code>center</code> et <code>baseline</code>.</p>


<p><strong><code>align-content</code></strong> prend par défaut la valeur <code>stretch</code>, et accepte également <code>flex-start</code>, <code>flex-end</code>, <code>center</code>, <code>space-between</code> et <code>space-around</code>.</p>


<h2>Propriétés sur les <code>flex-items</code></h2>
<p>Passons maintenant aux propriétés qui s’appliquent sur les enfants directs du <i>flex-container</i> et commençons par la plus riche : <code>flex</code>.</p>
<hr/>
<p>Ne confondez pas : nous avons vu plus haut ce mot-clef comme une nouvelle <em>valeur</em> de <code>display</code> ; il s’agit maintenant d’une nouvelle <em>propriété</em>.</p>
<h3>Les dimensions</h3>
<p><strong><code>flex</code></strong> est une propriété raccourcie qui combine <code>flex-grow</code>, <code>flex-shrink</code> et <code>flex-basis</code>.</p>
<pre><code>.baz
{
    flex: 0 1 auto;
}</code></pre>
<p>a donc pour équivalent :</p>
<pre><code>.baz
{
    flex-grow: 0;
    flex-shrink: 1;
    flex-basis: auto;
}</code></pre>
<ul>
<li><code>flex-grow</code> définit les possibilités d’étirements d’un élément,</li>
<li><code>flex-shrink</code> ses possibilités de contractions,</li>
<li>et <code>flex-basis</code> sa dimension initiale.</li>
</ul>
<p>Par étirement et contraction, comprenez par là qu’un élément pourra voir sa taille surchargée afin de répondre au mieux à vos conditions et au contexte d’affichage courant.</p>
<p><strong><code>flex-grow</code></strong> ne permet pas d’étirement quand il est à <code>0</code>, il faut passer un nombre positif plus ou moins important pour changer ce comportement par défaut.</p>




<hr/>
<p>Nous expliciterons un peu plus loin (avec <code>flex-basis</code>) la méthode de calcul qui définit les agrandissements. </p>
<hr/>
<p><strong><code>flex-shrink</code></strong> a pour valeur initiale 1 : la contraction est donc possible par défaut. On pourra lui passer un nombre nul ou un nombre positif pour annuler ou amplifier ce comportement.</p>
<p>Plus un <code>flex-shrink</code> sera important, plus l’élément sera à même d’être compressé.</p>




<p><strong>Comment sont calculées les compressions ?</strong></p>
<p>Lorsque les facteurs de compression sont identiques, les proportions entre les éléments sont conservées.</p>
<p>Dans le prochain exemple la taille du conteneur est revue (et animée) de manière à compresser les <i lang="en"> flex-items</i> dont les largeurs sont définies en pixels. </p>
<p>On constate une largeur identique entre le premier <i lang="en"> flex-item</i> et les trois suivants quelle que soit la taille du <i lang="en">flex-container</i>.<br/>
Et il en va de même pour les largeurs des trois derniers <i lang="en"> flex-items</i> qui restent identiques.</p>


<p>Vous aurez peut-être noté que la largeur initiale des éléments intervient dans les calculs. Ainsi un élément deux fois plus large qu’un autre (et pourtant le même facteur de compression) se verra proportionnellement deux fois plus compressé si nécessaire.</p>


<p>Quand les facteurs de compression sont différents, l’espace retiré lors de la compression est aussi proportionnel au facteur de compression.</p>
<p>On constate ici que l’espace retiré du dernier <i lang="en"> flex-item</i> est trois fois plus grand que sur le second ; ainsi que deux fois plus grand que sur le troisième.<br/>
Aucun espace n’est par contre retiré du premier.</p>


<p>Ce sont donc les facteurs de compressions et les tailles initiales des éléments qui influent sur le taux de compression possible de chacun.</p>
<p><strong><code>flex-basis</code></strong> est une propriété qui hérite par défaut (avec la valeur <code>auto</code>) de la largeur (<code>width</code>) ou de la hauteur (<code>height</code>) d’un élément, et ce en fonction de la direction définie sur le <i lang="en">flex-container</i>. </p>
<p>Elle peut aussi prendre une valeur qui viendra surcharger cette dimension.</p>
<p><code>flex-basis</code> va également redéfinir la taille minimale d’un élément (<code>min-width</code> ou <code>min-height</code>) et faire passer sa valeur par défaut de <code>0</code> à <code>auto</code>.</p>
<p>On peut ainsi définir un <code>flex-basis</code> à <code>0</code>, tout en conservant visuellement une taille minimale pour l’élément.</p>
<p><strong>Comment sont calculés les agrandissements ?</strong></p>
<p>Ce qui est très intéressant avec <code>flex-basis</code>, c’est qu’il entre en jeu pour les calculs de dimensionnement : sa valeur va donc considérablement influencer les comportements d’agrandissement.</p>
<ul>
<li>Quand <code>flex-basis</code> est à <code>0</code>, c’est la taille des <i lang="en">flex-items</i> qui sera revue ;</li>
<li>quand <code>flex-basis</code> est à <code>auto</code>, c’est l’espace restant qui sera revu.</li>
</ul>


<h3>La justification sur l’axe secondaire</h3>
<p><code>align-items</code> (que nous avons vu plus haut) permet de justifier tous les éléments au sein d’un conteneur.</p>
<p><strong><code>align-self</code></strong> permet de cibler individuellement ses enfants.</p>
<p>Par défaut il est à <code>auto</code> et hérite du comportement du <i lang="en">flex-container</i> mais on retrouve les même valeurs possibles que pour <code>align-items</code>. À savoir :  <code>flex-start</code>, <code>flex-end</code>, <code>center</code>, <code>baseline</code> et <code>stretch</code>.</p>


<h3>L’ordonnancement</h3>
<p><strong><code>order</code></strong> accepte uniquement des nombres entiers (négatifs ou positifs) et permet d’ordonner les éléments dans le flux. Il est fixé à <code>0</code> par défaut.</p>






<p>Les ordres qui sont appliqués aux éléments sont alors classés par ordre croissant et c’est tout le flux d’affichage qui peut s’en retrouver modifié.</p>
<hr/>
<p>Outre cette compréhension basique des propriétés, il faudra bien sûr à l’avenir mieux appréhender l’utilisation de ce nouveau module. Agencements de propriétés, dégradations possibles, bugs…</p>
<p>Par bien des aspects, je trouve que <i lang="en">flexbox</i> mélange les avantages des flottants et les avantages des tableaux. Nul doute : si vous êtes amenés à travailler dans des contextes responsifs, les possibilités offertes par <i lang="en">flexbox</i> vous intéresseront.</p>
<hr/>
<p>Voici pour compléter une liste de liens sur le sujet :</p>

<ul>
<li><a href="http://www.alsacreations.com/tuto/lire/1493-css3-flexbox-layout-module.html">article général en français</a> ;</li>
<li><a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/">article général en anglais</a> ;</li>
<li><a href="http://la-cascade.ghost.io/tag/flexbox/">mises en applications commentées</a> ;</li>
<li><a href="http://www.alsacreations.com/tuto/lire/1659-une-grille-responsive-avec-flexbox-et-LESS.html">une grille de mise en page</a> ;</li>
<li><a href="http://tzi.github.io/chewing-grid.css/">une seconde grille de mise en page</a> ;</li>
<li><a href="http://jackintheflexbox.tumblr.com/">des exemples pratiques</a> ;</li>
<li><a href="http://philipwalton.github.io/solved-by-flexbox/">d’autres exemples</a> ;</li>
<li><a href="https://github.com/philipwalton/flexbugs">une liste de bugs</a> ;</li>
<li><a href="http://chriswrightdesign.com/experiments/flexbox-adventures/">un article qui s’attarde un peu plus sur les calculs d’agrandissements et de compressions</a> ;</li>
<li><a href="http://caniuse.com/#search=flexbox">le support actuel</a> ;</li>
<li><a href="http://www.w3.org/TR/css3-flexbox/">la spécification</a>.</li>
</ul>

<p>Bonnes lectures et bonnes expérimentations à tous.</p>
