Flexbox est une méthode de mise en page unidimensionnelle pour disposer des éléments en ligne ou en colonne. Les éléments se dilatent ou se rétractent pour occuper l'espace disponible. Cet article en explique tous les fondamentaux.

Prérequis : Les fondamentaux du HTML (étudiez Introduction au HTML) et avoir une idée de la manière dont la CSS fonctionne (étudiez Introduction aux CSS).
Objectif : Apprendre à utiliser le système Flexbox pour créer des mises en page web.

Pourquoi Flexbox ?

Pendant longtemps, les seuls outils, fiables et compatibles entre navigateurs, disponibles pour créer des mises en page CSS étaient des choses comme les flotteurs (boîtes flottantes) et le positionnement. Ces outils sont bien et fonctionnent, mais à certains égards, ils sont aussi plutôt limitatifs et frustrants.

Les simples exigences de mise en page suivantes sont, soit difficiles, soit impossibles à réaliser de manière pratique et souple avec ces outils :

  • centrer verticalement un bloc de contenu dans son parent.
  • faire que tous les enfants d'un conteneur occupent tous une même quantité de hauteur/largeur disponible selon l'espace offert.
  • faire que toutes les colonnes dans une disposition multi‑colonnes aient la même hauteur même si la quantité de contenu diffère.

Comme vous le verrez dans les paragraphes suivants, flexbox facilite considérablement les tâches de mise en page. Approfondissons un peu !

Voici un exemple simple

Dans cet article, nous allons commenter une série d'exercices pour vous faciliter la compréhension du fonctionnement de flexbox. Pour commencer, faites une copie locale du premier fichier de démarrage — flexbox0.html de notre dépôt github —, chargez‑le dans un navigateur moderne (comme Firefox ou Chrome) et regardez le code dans votre éditeur. Vous pouvez le voir en direct ici aussi.

Qu'avons‑nous ? un élément <header> avec un en‑tête de haut niveau dedans et un élément <section> contenant trois <article>s. Nous allons les utiliser pour créer une disposition vraiment classique sur trois colonnes.

Échantillon d'utilisation de flexbox

Indication des éléments à déposer dans des boîtes modulables

Pour commencer, sélectionnons les éléments devant être présentés sous forme de boîtes modulables. Pour ce faire, donnons une valeur spéciale à la propriété  display du parent des éléments à disposer. Dans ce cas, comme nous voulons y placer les éléments <article>, nous affectons la valeur flex à l'élément <section> (qui devient un conteneur modulaire) :

section {
  display: flex;
}

Voici le résultat :

Échantillon d'utilisation de flexbox

Ainsi, cette unique déclaration donne tout ce dont nous avons besoin — incroyable, non ? Nous avons notre disposition en colonnes multiples de largeur égale toutes de même hauteur. C'est parce que les valeurs par défaut données aux éléments flex (les enfants du conteneur flex) sont configurés pour résoudre des problèmes courants tels celui-ci. On en reparlera plus tard.

Note : Vous pouvez aussi définir une valeur inline-flex pour  display si vous voulez disposer des éléments en ligne sous forme de boîtes modulables.

Aparté sur le modèle flex

Lorsque les éléments sont disposés en boîtes modulables, ils sont disposés le long de deux axes :

Terminologie pour les boîtes modulables

  • L'axe principal (main axis) est l'axe de la direction dans laquelle sont disposés les éléments flex (par exemple, horizontalement au travers de la page ou verticalement de haut en bas de la page). Le début et la fin de cet axe sont appelés l'origine principale (main start) et la fin principale (main end).
  • L'axe croisé  est l'axe perpendiculaire à la direction dans laquelle sont disposés les éléments flex. Le début et la fin de cet axe sont appelés le début (cross start) et la fin (cross end) de l'axe croisé.
  • L'élément parent dont la propriété est display: flex  (<section> dans notre exemple) est appelé le conteneur flex (flex container).
  • Les éléments disposés en tant que boîtes modulables à l'intérieur du conteneur flex sont appelés éléments flex (flex items) (les éléments <article>} dans notre exemple).The items being laid out as flexible boxes inside the flex container are called (the <article> elements in our example).

Gardez cette terminologie en tête en lisant les paragraphes suivants. Vous pouvez toujours vous y référer si vous avez un doute sur la signification des termes utilisés.

Colonnes ou rangées ?

 

Flexbox dispose de la propriété flex-direction pour indiquer la direction de l'axe principal (direction dans quelle les enfants flexbox sont disposés) — par défaut, cette propriété est égale à row : ils sont donc disposés en ligne dans le sens de lecture de la langue par défaut du navigateur (de gauche à droite, dans le cas d'un navigateur français).

Ajoutons la déclaration suivante dans la règle :

flex-direction: column;

Cela dispose à nouveau les éléments en colonnes, comme c'était le cas avant l'ajout de la CSS. Avant de poursuivre, enlevez cette déclaration de l'exemple.

Note : Vous pouvez aussi disposer les éléments flex dans la direction inverse avec les valeurs row-reverse et column-reverse. Expérimentez ces valeurs aussi !

Conditionnement

Problème : quand votre agencement est de largeur ou hauteur fixe, il arrive que les enfants flexbox débordent du conteneur et brisent cet agencement. Voyez l'exemple flexbox-wrap0.html, essayez directement (faites une copie locale de ce fichier maintenant si vous voulez suivre cet exemple) :

Débordement des éléments modulables

Ici, nous voyons que les enfants débordent du conteneur. Une façon d'y remédier est d'ajouter la déclaration suivante à votre règle pour section :

flex-wrap: wrap;

Essayons ; la disposition est bien meilleure avec cet ajout :

Conditionnement des éléments modulablesNous avons maintenant plusieurs rangées — autant d'enfants flexbox sont placés sur chaque rangée comme il se doit et le débordement est déplacé vers le bas sur une ligne supplémentaire. La déclaration flex: 200px pour les éléments article signifie que chacun aura au moins 200px de large ; nous discuterons de cette propriété plus en détail plus tard. Vous noterez aussi que les derniers enfants de la dernière rangée sont chacun plus larges pour faire en sorte que toute la rangée soit encore remplie.

Mais nous pouvons faire plus ici. Tout d'abord, essayez de changer la valeur de la propriété flex-direction en row-reverse — maintenant vous avez toujours la disposition sur plusieurs lignes, mais elle commence dans l'angle opposé de la fenêtre du navigateur et est déroulée à l'envers.

Forme abrégée « flex-flow »

Notez maintenant qu'il y a une forme abrégée pour flex-direction et flex-wrapflex-flow. Ainsi, par exemple, vous pouvez remplacer

flex-direction: row;
flex-wrap: wrap;

par

flex-flow: row wrap;

Taille modulable des éléments flex

Revenons maintenant au premier exemple, et examinons comment nous pouvons contrôler la proportion d'éléments modulables dans l'espace. Lancez votre copie locale de flexbox0.html ou prenez une copie de flexbox1.html comme nouveau point de départ (voir en direct).

Primo, ajoutez la règle ci-après en fin de la CSS :

article {
  flex: 1;
}

Il s'agit d'une valeur de proportion sans unité définissant la quantité d'espace disponible le long de l'axe principal que chaque élément flex prendra. Dans ce cas, nous donnons à chaque élément <article>} une valeur de 1, ce qui signifie qu'ils prendront tous une quantité égale de l'espace libre laissé après que le remplissage  et la marge auront été réservés. Il s'agit d'une proportion, ce qui signifie que le fait de donner une valeur de 400 000 simultanément à tous les éléments flex aurait exactement le même effet.

Maintenant ajoutons cette règle en dessous de la précédente :

article:nth-of-type(3) {
  flex: 2;
}

Maintenant, lorsque vous actualisez, vous voyez que le troisième <article> occupe deux fois plus de largeur disponible que chacun des deux autres — il y a maintenant quatre unités de division disponibles au total. Les deux premiers éléments modulables en occupent un chacun, soit 1/4 de l'espace disponible chacun. Le troisième en occupe deux unités, soit 2/4 (la moitié) de l'espace disponible.

Vous pouvez également définir une valeur minimale de taille dans la valeur flex. Modifiez comme suit vos règles article existantes :

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 2 200px;
}

En gros, cela dit : « Chaque élément flex reçoit d'abord 200px de l'espace disponible. Ensuite, le reste de l'espace disponible est réparti selon les unités de proportion ». Actualisez et vous devriez voir une différence dans la façon dont l'espace est réparti.

Modulation de la largeur

Le véritable intérêt de flexbox apparaît dans sa souplesse/réactivité — si vous redimensionnez la fenêtre du navigateur ou ajoutez un autre élément <article>}, la mise en page continue de fonctionner correctement.

flex : forme abrégée vs longue

flex est une forme abrégée de propriété qui peut servir à définir trois valeurs différentes :

  • la valeur de proportion sans unité vue ci‑dessus. Elle peut être précisée seule avec la forme longue de la propriété flex-grow.
  • une deuxième valeur de proportion sans unité — flex-shrink — intervenant quand les éléments flex débordent du conteneur. Elle indique la quantité de débordement à retirer de la taille de chacun des éléments flex pour les empêcher de déborder du conteneur. Il s'agit d'une fonctionnalité avancée de flexbox, et nous n'en parlerons plus dans cet article.
  • la valeur de taille minimale vue ci‑dessus. Elle peut être précisée seule avec la forme longue de la propriété flex-basis.

Nous vous déconseillons d'utiliser les propriétés flex sous leur forme longue sauf impossibilité alternative (par exemple, pour annuler quelque chose déjà défini). Elles amènent l'écriture de code supplémentaire et peuvent être quelque peu déroutantes.

Alignement horizontal et vertical

Vous pouvez également utiliser les fonctionnalités de flexbox pour aligner les éléments flex le long de l'axe principal ou transversal. Voyons cela avec un nouvel exemple — flex-align0.html (voir aussi en direct). Nous allons le transformer facilement en une barre de boutons/outils souple. Actuellement, nous avons une barre de menu horizontale avec quelques boutons tassés dans l'angle supérieur gauche.

Alignement

D'abord, faites une copie locale de cet exemple.

Ensuite, ajoutez ce qui suit à la fin de la CSS de l'exemple :

div {
  display: flex;
  align-items: center;
  justify-content: space-around;
}

Actualisez la page et vous verrez que les boutons sont maintenant bien centrés, horizontalement et verticalement. Cette transformation a été opérée grâce à deux nouvelles propriétés.

align-items contrôle là où les éléments flex sont placés sur l'axe en croix (cross axis).

  • Par défaut, la valeur est stretch, qui tasse tous les éléments flex de manière à emplir le conteneur parent dans le sens de l'axe en croix. Si le parent n'a pas de largeur définie dans la direction de l'axe en croix, alors tous les éléments flex auront la longueur du plus long des éléments. C'est pour cette raison que, dans notre premier exemple, les colonnes ont toutes la même hauteur par défaut.
  • La valeur center, utilisée dans le code ci-dessus, fait que les éléments gardent leurs dimensions intrinsèques, tout en étant centrées le long de l'axe en croix. C'est pourquoi les boutons de l'exemple actuel sont centrés verticalement.
  • Il y a également des valeurs comme flex-start et flex-end qui alignent respectivement tous les éléments au début et à la fin de l'axe en croix. Voyez align-items pour tous les détails.

Vous pouvez prendre le pas sur le comportement de align-items pour des éléments flex donnés en leur appliquant la propriété align-self. Par exemple, ajoutez ce qui suit à la CSS:

button:first-child {
  align-self: flex-end;
}

Voyez l'effet obtenu, puis supprimez la règle ensuite.

justify-content contrôle là où les éléments flex sont placès sur l'axe principal.

  • La valeur par défaut est flex-start. Tous les éléments sont placés à l'origine de l'axe principal.
  • Vous utiliserez  flex-end pour les placer à la fin.
  • center est aussi une valeur possible pour justify-content. Elle fait que les éléments flex sont placés au centre de l'axe principal.
  • La valeur space-around, utilisée plus haut, est pratique — elle distribue tous les éléments régulièrement le long de l'axe principal en laissant un petit peu d'espace à chaque extrémité.
  • Une autre valeur, space-between, est semblable à space-around mais elle ne laisse pas d'espace aux extrémités.

N'hésitez pas à jouer avec ces valeurs pour voir leur fonctionnement avant de poursuivre.

Ordonner les éléments flex

Flexbox dispose aussi d'une fonctionnalité pour modifier l'ordre d'affichage des éléments flex, sans modifier en modifier l'ordre dans le source. C'est une chose impossible à réaliser avec les méthodes classiques de mise en page.

Le code pour ce faire est simple : ajoutez la règle CSS suivante dans l'exemple de code de la barre de boutons :

button:first-child {
  order: 1;
}

Actualisez, et vous pouvez voir que le bouton « Smile » a été déplacé en fin de l'axe principal. Voyons comment cela fonctionne dans le détail :

  • par défaut, tous les éléments flex ont une valeur order égale à 0.
  • les éléments flex avec des valeurs de order plus élévées apparaîtront plus tard dans l'ordre d'affichage que ceux avec des valeurs plus faibles.
  • les éléments flex avec les mêmes valeurs pour order sont affichés dans l'ordre du source. Ainsi, si vous avez 4 éléments avec des valeurs order de 2, 1, 1 et 0, leur ordre d'affichage sera 4e, 2e, 3e et premier.
  • Le troisième élément suit le deuxième, car il a la même valeur pour order et qu'il est placé après dans le source.

Vous pouvez donner des valeurs négatives à order pour faire en sorte que ces éléments soient affichés avant les éléments d'ordre 0. Par exemple, vous pouvez faire apparaître le bouton « Blush » en tête de l'axe principal avec la règle suivante :

button:last-child {
  order: -1;
}

Boîtes flex imbriquées

Il est possible de créer des mises en page joliment complexes avec flexbox. Il es parfaitement loisible de déclarer un élément flex en tant que conteneur flex, de sorte que ses enfants sont également disposés en tant que boîtes modulables. Regardez complex-flexbox.html (à voir en direct également).

Imbrications avec flexbox

Le HTML pour cela est vraiment simple. Voici un élément <section> contenant trois éléments <article>. Le troisième élément <article> contient trois éléments <div> :

section - article
          article
          article - div - button   
                    div   button
                    div   button
                          button
                          button

Voyez le code utilisé pour cette disposition.

Primo, nous décidons que les enfants de l'élément <section> seront des boîtes modulables.

section {
  display: flex;
}

Secundo, nous définissons des valeurs flex pour les éléments <article> eux‑mêmes. Remarquez en particulier la deuxième règle ici — nous paramétrons le troisième élément <article> pour que ses enfants soient eux-mêmes disposés en tant qu'éléments modulables, mais cette fois‑ci en colonne.

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 3 200px;
  display: flex;
  flex-flow: column;
}

Tertio, nous sélectionnons le premier élément <div> et lui assignons la valeur flex:1 100px; pour qu'il ait effectivement une hauteur minimale de 100px, ensuite nous indiquons que ses enfants (les éléments <button>) doivent être disposés en tant qu'éléments flex, sous forme d'une rangée enveloppe, centrés dans l'espace disponible comme dans l'exemple des boutons vu plus haut.

article:nth-of-type(3) div:first-child {
  flex:1 100px;
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  justify-content: space-around;
}

Enfin, nous définissons un dimensionnement des boutons, mais plus particulièrement nous leur donnons une valeur flex de 1. L'effet obtenu est très intéressant ; vous l'observerez en modifiant la largeur de la fenêtre du navigateur. Les boutons prennent autant d'espace qu'il leur est permis et sont disposés sur la même ligne si possible, mais si ce n'est pas possible, il descendent  pour créer de nouvelles lignes.

button {
  flex: 1;
  margin: 5px;
  font-size: 18px;
  line-height: 1.5;
}

Compatibilité croisée des navigateurs

La prise en charge de Flexbox est disponible avec la plupart des nouveaux navigateurs — Firefox, Chrome, Opera, Microsoft Edge et IE 11, les nouvelles versions d'Android/iOS, etc. Mais vous devez être attentif au fait que l'on utilise encore des navigateurs anciens qui ne prennent pas en charge Flexbox (ou le font, mais uniquement pour des versions très anciennes, vraiment dépassées).

Pour l'apprentissage et l'expérimentation, cela n'a pas trop d'importance. Mais utiliser flexbox dans un site Web réel nécessite de faire des tests et de s'assurer que l'expérience utilisateur est toujours acceptable dans le plus grand nombre de navigateurs possible.

Flexbox est une fonctionnalité plus complexe que les règles CSS courantes. Par exemple, ne pas avoir la prise en charge des ombres portées dans la CSS fera que le site restera utilisable. Mais ne pas prendre en charge les fonctionnalités flexbox risque de casser totalement la mise en page et de rendre le site inutilisable.

Les stratégies pour contourner les problèmes de prise en charge croisée des navigateurs est discutée dans le module Tests croisés sur navigateurs.

Résumé

Notre visite guidée des fondements de flexbox est maintenant terminée. Espérons que vous en êtes satisfaits et que vous saurez jouer avec ses fonctionnalités tout en progressant dans l'apprentissage. Nous allons examiner en suivant un autre aspect important de la mise en page avec les CSS — les trames CSS.

Étiquettes et contributeurs liés au document

Contributeurs à cette page : Dralyab
Dernière mise à jour par : Dralyab,