CSS (Cascading Style Sheets)

Auteur: Mohamed CHINY Durée necessaire pour le cours de CSS (Cascading Style Sheets) Niveau recommandé pour le cours de CSS (Cascading Style Sheets) Supports vidéo non disponibles pour ce cours Exercices de renforcement disponibles pour ce cours Quiz disponible pour ce cours

Page 15: Flexbox - les boites flexibles

Toutes les pages

Les boites flexibles en CSS (Flexbox)

En général, il y a deux types d'objets en HTML, des objets inline et des objets block.
  • Les objets inline: sont des objets qui occupent juste l'espace necessaire pour leur affichage, il ne génèrent pas de retour à la ligne automatique et ne sont pas redimensionnables en CSS (sauf quelques exceptions comme les blaises <img /> ou <input />). C'est le cas des balises <span>, <b>, <i>...
  • Les objets block: sont des objets qui par défaut occupent la ligne entière (ou block de plusieurs lignes) et engendrent ainsi un retour à la ligne avant et après. C'est le cas des balises <div>, <form>, <p>, <header>, <nav>...


Si on souhaite avoir un objet redimensionnable et qu'on peut mettre sur une ligne qui contient déjà un autre objet (inline) alors une solution a été proposée en CSS3; il s'agit de display:inline-block. D'autres solutions sont aussi possibles et la plus célèbre est le flottement (float).

Cependant, avec ces solutions là (display:inline-block ou float:left/right) la mise en page de plusieurs objets sur la même ligne s'avère difficile à maitriser. Des fois, un minuscule pixel de plus peut faire s'écrouler tout le design. Mais une solution magique a été introduite en CSS, il s'agit de Flexbox ou boites flexibles.

Qu'est ce qu'une flexbox?

Une flexbox (pour flexible box ou boite flexible) est un conteneur qui renferme des éléments (inline ou block) de telle sorte à ce que ces éléments là soient emboités d'une manière flexible sans générer de débordement ou de retour à la ligne incontrôlé.

En gros une flexbox permet:
  • La distribution des éléments horizontalement ou verticalement en spécifiant comment gérer les espaces restants.
  • L'aligenement des éléments d'une manière fluide et personnalisée.
  • L'organisation des élément dans un ordre qui peut être différent de celui établi par le flux du DOM.

Rendre un conteneur flexible

Généralement, les conteneurs sont de type block comme c'est le cas pour les balises <div>, <section>, <aside>... Afin de les rendre flexibles (ou flexbox) il faut changer leur propriété CSS display comme ceci:
élement{
   display: flex;
}
Ainsi tous les éléments enfants de l'élément flexbox seront réaligné par défaut de manière à ce qu'ils soient tous sur la même ligne (même s'ils sont de type block).

Prenons le code suivant:
<div id="flexbox">
   <div class="enfant">ENFANT 1</div>
   <div class="enfant">ENFANT 2</div>
   <div class="enfant">ENFANT 3</div>
</div>
Si on exécute ce code on obtient quelque chose comme ceci:
ENFANT 1
   
ENFANT 2
   
ENFANT 3
Sans surprise, les DIV enfant sont alignés l'une en dessous de l'autre, ce qui est un comportement normal.

Appliquons maintenant la propriété display:flex sur le conteneur (#flexbox):
<style>
   #flexbox{
      display:flex;
   }
</style>
<div id="flexbox">
   <div class="enfant">ENFANT 1</div>
   <div class="enfant">ENFANT 2</div>
   <div class="enfant">ENFANT 3</div>
</div>
Le résultat obtenu est:
ENFANT 1
   
ENFANT 2
   
ENFANT 3
Vous constatez que les éléments enfant sont désormais aligné sur la même ligne, et en plus leur largeur a automatiquement été réduite pour correspondre à leur juste contenu.

Essayons maintenant d'appliquer une largeur de 100% sur tous les éléments enfants:
<style>
   #flexbox{
      display:flex;
   }
   .enfant{
      width:100%;
   }
</style>
<div id="flexbox">
   <div class="enfant">ENFANT 1</div>
   <div class="enfant">ENFANT 2</div>
   <div class="enfant">ENFANT 3</div>
</div>
Le résultat obtenu est:
ENFANT 1
   
ENFANT 2
   
ENFANT 3
Vous avez remarqué que la largeur a automatiquement été rectifiée par le navigateur pour que les trois éléments enfant soient emboités dans la même ligne. Je vous laisse donc imaginer les innombrables possibilités que cela peut offrir pour mieux maitriser le positionnement de ses éléments sans se soucier de calculer minutieusement les largeurs au pixel près.
Notez que les flexbox sont compatibles avec tous les navigateurs actuels. Pour Inernet Explorer, la prise en charge de la propriété flex commence à partir de la version 10.

Aller plus loin avec flexbox

Définition de l'axe principal: propriété flex-direction

Un conteneur quelconque dispose de deux axes, un axe principal et un axe secondaire qui, par défaut, correspondent respectivement aux axes horizontal et vertical.

Dans l'exemple précédent nous avons vu que les éléments ont été distribué horizontalement après l'application de la propriété display:flex sur le parent. En effet, il s'agit là de l'axe principal.

La propriété que l'on peut appliquer sur le conteneur pour changer la direction par défaut de l'axe principal est flex-direction et qui peut prendre les valeurs suivantes:
  • row: qui est la valeur par défaut, est qui distribue les éléments enfant sur l'axe horizontal dans l'ordre de flux (par défaut, de gauche à droite). Si vous appliquez l'attribut HTML dir:rtl alors l'alignement sera effectuée de droite à gauche.
  • column: dans ce cas la distribution des éléments enfant sera effectuée sur l'axe vertical de haut en bas.
  • row-reverse: la distribution sera faite suivant l'axe horizontal mais dans l'ordre inversé.
  • column-reverse: la distribution sera faite suivant l'axe vertical mais dans l'ordre inversé (du bas vers le haut).

Exemple:
<style>
   #flexbox{
      display:flex;
      flex-direction:row-reverse;
   }
   .enfant{
      width:100%;
   }
</style>
<div id="flexbox">
   <div class="enfant">ENFANT 1</div>
   <div class="enfant">ENFANT 2</div>
   <div class="enfant">ENFANT 3</div>
</div>
On obtient:
ENFANT 1
   
ENFANT 2
   
ENFANT 3

Alignement sur l'axe principal: propriété justify-content

Pour aligner les éléments sur l'axe principal on fait appel à la propriété justify-content et peut prendre les valeurs suivantes:
  • flex-start: (valeur par défaut) les éléments enfant seront alignés l'axe principal dans l'ordre normal du flux au début du conteneur.
  • flex-end: les éléments enfant seront aligné à la fin du conteneur.
  • space-between: les éléments seront répartis sur tout l'axe principal, si leur largeur combinées est inférieur à celle du conteneur alors un espacement sera placé entre deux enfants voisins d'une manière régulière.
  • space-around: les éléments seront répartis sur tout l'axe principal, si leur largeur combinées est inférieur à celle du conteneur alors un espacement sera placé autour de tous les enfants.
  • center: les éléments seront centrés dans le conteneur.

Exemple 1:
<style>
   #flexbox{
      display:flex;
      justufy-content:space-between;
   }
   .enfant{
      width:auto;
   }
</style>
<div id="flexbox">
   <div class="enfant">ENFANT 1</div>
   <div class="enfant">ENFANT 2</div>
   <div class="enfant">ENFANT 3</div>
</div>
On obtient:
ENFANT 1
   
ENFANT 2
   
ENFANT 3
Exemple 2:
<style>
   #flexbox{
      display:flex;
      justufy-content:space-around;
   }
   .enfant{
      width:auto;
   }
</style>
<div id="flexbox">
   <div class="enfant">ENFANT 1</div>
   <div class="enfant">ENFANT 2</div>
   <div class="enfant">ENFANT 3</div>
</div>
On obtient:
ENFANT 1
   
ENFANT 2
   
ENFANT 3

Alignement sur l'axe secondaire: propriété align-items

Pour contrôler l'alignement sur l'axe secondaire (l'axe vertical par défaut du conteneur) on utilise la propriété align-itemsw qui peut prendre les valeurs suivantes:
  • flex-start: (valeur par défaut) les éléments enfant seront alignés l'axe secondaire dans l'ordre normal du flux au début du conteneur.
  • flex-end: les éléments enfant seront aligné à la fin du conteneur.
  • stretch: si le éléments enfant ont des hauteurs différentes alors elles seront étirés jusqu'à ce qu'ils aient la même hauteur.
  • center: les éléments seront centrés dans le conteneur.

Exemple 1:
<style>
   #flexbox{
      display:flex;
      align-items:flex-end;
   }
   .enfant{
      width:auto;
   }
</style>
<div id="flexbox">
   <div class="enfant">ENFANT 1</div>
   <div class="enfant">ENFANT 2</div>
   <div class="enfant">ENFANT 3</div>
</div>
On obtient:
ENFANT 1
   
ENFANT 2
   
ENFANT 3
Exemple 2:
<style>
   #flexbox{
      display:flex;
      justify-content:center;
      align-items:center;
   }
   .enfant{
      width:auto;
   }
</style>
<div id="flexbox">
   <div class="enfant">ENFANT 1</div>
   <div class="enfant">ENFANT 2</div>
   <div class="enfant">ENFANT 3</div>
</div>
On obtient:
ENFANT 1
   
ENFANT 2
   
ENFANT 3

Changement de l'ordre par défaut: propriété order

Par défaut, les éléments enfant sont affichés soit dans l'ordre du flux ou l'ordre inverse (flex-end). Toutefois, on peut établir un ordre tout à fait personnalisé sans toucher au code HTML. C'est possible grâce à la propriété order que l'on applique sur l'élément enfant.
Exemple:
<style>
   #flexbox{
      display:flex;
      justify-content:center;
      align-items:center;
   }
   .enfant{
      width:auto;
   }
</style>
<div id="flexbox">
   <div class="enfant" style="order:2">ENFANT 1</div>
   <div class="enfant" style="order:3">ENFANT 2</div>
   <div class="enfant" style="order:1">ENFANT 3</div>
</div>
On obtient:
ENFANT 1
   
ENFANT 2
   
ENFANT 3

Elasticité (ou flexibilité): propriété flex

Il est possible de doter un élément enfant d'une largeur (ou hauteur) qui fait le double ou le triple... de ses voisins d'une manière fluide. C'est possible grâce à la propriété flex qui prend une valeur numérique qui désigne le multiplicateur de taille. Cette propriété est appliquée sur l'élément enfant:
Exemple:
<style>
   #flexbox{
      display:flex;
      justify-content:center;
      align-items:center;
   }
   .enfant{
      width:auto;
   }
</style>
<div id="flexbox">
   <div class="enfant" style="flex:2">ENFANT 1</div>
   <div class="enfant" style="flex:1">ENFANT 2</div>
   <div class="enfant" style="flex:3">ENFANT 3</div>
</div>
On obtient:
ENFANT 1
   
ENFANT 2
   
ENFANT 3

Conclusion

Flexbox est une boite à outils riche et remarquablement pratique puisqu'elle simplifie nettement la mise en page et le contrôle de ses éléments sans se soucier de leurs dimensions ou leurs bordures ou encore leur marge internes ou externes. Leur emboitement devient facile à gérer et leur ordre d'affichage aussi. Alors fini les éléments flottants et les calculs des dimensions pixel par pixel pour éviter les débordements.