Flexbox expliqué simplement : le guide français complet
Si vous avez déjà passé une soirée à essayer de centrer un bloc ou d’aligner trois cartes côte à côte, cet article est pour vous. Flexbox est le module CSS qui a rendu ces galères obsolètes : un réglage sur le parent, deux ou trois sur les enfants, et la mise en page suit. C’est le guide promis à la fin de l’article sur les dimensions et le positionnement en CSS, et il se suffit à lui-même si vous arrivez directement ici.
Une précision avant de commencer : tous les exemples de cette page ont été exécutés dans Chrome 151 pendant la rédaction. Quand j’écris qu’un bloc mesure 166,67 px ou qu’il se place à 250 px du bord, ce sont des valeurs mesurées dans le navigateur, pas des chiffres théoriques. Vous pouvez copier chaque extrait et vérifier chez vous.
Le principe : un parent flex, des enfants qui s’adaptent
Flexbox repose sur une idée simple : on ne positionne pas les blocs un par un, on donne une consigne au conteneur et il place ses enfants tout seul. Tout démarre avec une seule déclaration :
<div class="conteneur">
<div>Un</div>
<div>Deux</div>
<div>Trois</div>
</div>
.conteneur {
display: flex;
}
L’effet est immédiat. Sans display: flex, mes trois div s’empilent et occupent chacune toute la largeur du conteneur (600 px dans mon test). Avec, elles se placent côte à côte et se resserrent sur leur contenu : j’ai mesuré 20, 37 et 35 px de large, soit juste la place du texte. Les enfants d’un conteneur flex ne se comportent plus comme des balises block ou inline classiques : ils obéissent à de nouvelles règles, celles de cet article.
Deux notions servent partout dans Flexbox, autant les poser tout de suite :
- l’axe principal : la direction dans laquelle les enfants se rangent (horizontale par défaut) ;
- l’axe transversal : la direction perpendiculaire (verticale par défaut).
flex-direction : choisir l’axe principal
Par défaut, l’axe principal est horizontal : les enfants forment une ligne. La propriété flex-direction permet d’en décider autrement :
.conteneur {
display: flex;
flex-direction: column; /* les enfants s'empilent */
}
Avec column, mes trois blocs se sont empilés en reprenant toute la largeur, comme des blocs classiques, mais en restant pilotables par toutes les propriétés qui suivent. Les valeurs row-reverse et column-reverse inversent l’ordre d’affichage sans toucher au HTML. Retenez surtout ceci : quand on passe en column, l’axe principal devient vertical, et toutes les propriétés d’alignement pivotent avec lui.
justify-content : distribuer l’espace sur l’axe principal
Quand les enfants n’occupent pas toute la largeur, il reste de l’espace libre. justify-content décide quoi en faire :
.conteneur {
display: flex;
justify-content: space-between;
}
Test concret : trois blocs de 100 px dans un conteneur de 600 px. Avec space-between, le premier se colle au bord gauche (position 0), le deuxième se place exactement à 250 px et le troisième finit à 500 px, contre le bord droit. L’espace libre (300 px) a été découpé en deux gouttières de 150 px. Les autres valeurs utiles :
flex-start(défaut) : tout à gauche ;center: le groupe est centré ;-
space-around: espace autour de chaque bloc (demi-gouttière aux extrémités) ; space-evenly: espaces tous identiques, bords compris.
align-items : aligner sur l’axe transversal
C’est le pendant vertical (par défaut) de la propriété précédente. La valeur par défaut, stretch, étire les enfants sur toute la hauteur du conteneur : c’est pour ça que des colonnes créées avec Flexbox ont naturellement la même hauteur. Pour centrer :
.conteneur {
display: flex;
align-items: center;
height: 200px;
}
Mesure : dans ce conteneur de 200 px de haut, mon bloc de 50 px se positionne à 75 px du haut. Le calcul tombe juste : (200 – 50) / 2 = 75. Le navigateur fait la soustraction à votre place, quelle que soit la taille du contenu.
Et c’est là qu’arrive la recette la plus copiée de tout CSS, le centrage parfait :
.conteneur {
display: flex;
justify-content: center; /* axe principal */
align-items: center; /* axe transversal */
}
Vérifié dans mon test : un bloc de 120 par 60 px dans un conteneur de 600 par 200 px atterrit à 240 px du bord gauche et 70 px du haut, soit un centrage exact sur les deux axes. Trois lignes, aucune marge à calculer.
gap : espacer les blocs sans margin
Longtemps, on espaçait les enfants avec des margin, avec le casse-tête du dernier élément qui n’en veut pas. La propriété gap règle ça au niveau du conteneur :
.conteneur {
display: flex;
gap: 16px;
}
Mesure avec trois blocs de 100 px : le deuxième commence à 116 px, le troisième à 232 px. Chaque gouttière fait exactement 16 px, et il n’y en a ni avant le premier bloc ni après le dernier. C’est précisément le comportement qu’on cherchait à bricoler avec les marges.
flex-grow, flex-shrink, flex-basis : qui prend combien de place ?
Jusqu’ici, le conteneur distribuait de l’espace autour des enfants. Les trois propriétés qui suivent se posent sur les enfants et pilotent leur taille elle-même.
flex-basis fixe la taille de départ d’un enfant sur l’axe principal. Mais attention, c’est une base de négociation, pas une garantie. La preuve : je place trois blocs avec flex-basis: 200px (600 px demandés au total) dans un conteneur de 500 px. Aucun ne déborde : Chrome les ramène chacun à 166,67 px. C’est flex-shrink qui agit, et il vaut 1 par défaut : les enfants acceptent de rétrécir pour tenir dans le conteneur.
Pour interdire ce rétrécissement sur un élément (un logo, une image, une colonne de largeur fixe), on le passe à zéro :
.bloc-fixe {
flex-basis: 200px;
flex-shrink: 0;
}
Rejouons le même test avec cette règle sur le premier bloc : il garde ses 200 px, et les deux autres absorbent toute la compression en tombant à 150 px chacun. Ce duo flex-basis + flex-shrink: 0 est le correctif classique des images écrasées dans une carte flex.
flex-grow fait l’inverse : il distribue l’espace libre. En pratique, on l’écrit presque toujours via le raccourci flex :
.colonne-laterale { flex: 1; }
.colonne-centrale { flex: 2; }
Test avec trois enfants en flex: 1, flex: 2, flex: 1 dans 600 px : j’obtiens 150, 300 et 150 px. Le conteneur a partagé la largeur en quatre parts et en a donné deux à l’enfant du milieu. Mon conseil : tenez-vous au raccourci flex: 1 (ou 2, ou 3) tant que vous débutez, il couvre l’immense majorité des besoins et évite de jongler avec les trois propriétés séparées.
flex-wrap : autoriser le passage à la ligne
Par défaut, un conteneur flex garde tous ses enfants sur une seule ligne, quitte à les compresser (on vient de le mesurer). Pour des cartes ou une galerie, on préfère souvent qu’ils passent à la ligne :
.conteneur {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
Mon test : quatre blocs de 150 px non rétrécissables dans un conteneur de 500 px. Les trois premiers tiennent sur la première ligne (482 px sur 500 en comptant les deux gouttières de 16 px, positions mesurées : 0, 166 et 332 px), le quatrième descend seul sur une deuxième ligne, sans media query ni calcul. En combinant flex-wrap, gap et un flex-basis raisonnable, on obtient une grille de cartes qui s’adapte à la largeur de l’écran quasi gratuitement.
Recette complète : la barre de navigation
Le cas pratique que tout le monde finit par coder : un menu avec le logo à gauche, les rubriques à côté et un bouton contact poussé tout à droite. Flexbox le résout avec une astuce à connaître, margin-left: auto :
<nav>
<a href="/" class="logo">Mon site</a>
<a href="/articles/">Articles</a>
<a href="/contact/" class="contact">Contact</a>
</nav>
nav {
display: flex;
align-items: center;
gap: 24px;
}
nav .contact {
margin-left: auto; /* pousse ce lien tout à droite */
}
Dans un conteneur flex, une marge en auto absorbe tout l’espace libre disponible. Mesure sur ma version de test (trois éléments de 90 px dans 600 px, gap de 24 px) : les deux premiers se placent à 0 et 114 px, le troisième est projeté à 510 px, collé au bord droit. Si vos liens sont bien structurés en HTML, ces dix lignes de CSS suffisent pour une barre de navigation propre.
Trois pièges à connaître
Flexbox n’agit que sur les enfants directs.
display: flex transforme les enfants immédiats du conteneur en éléments flex, pas leurs descendants. Si vos blocs sont enveloppés dans une div intermédiaire, c’est elle qui devient l’élément flex, et l’intérieur ne bouge pas. Quand « rien ne se passe », vérifiez d’abord qui est réellement enfant direct.
Les enfants rétrécissent par défaut. C’est la mesure la plus contre-intuitive de cet article : demander 200 px et en obtenir 166,67. Tant que vous n’avez pas posé flex-shrink: 0, aucune largeur n’est garantie dans un conteneur flex. Ce comportement est une force (rien ne déborde) mais il surprend toujours la première fois.
Les tailles se calculent sur le modèle de boîte. Padding et bordures s’ajoutent aux largeurs négociées par Flexbox exactement comme ailleurs en CSS. Si vos comptes ne tombent pas juste, relisez le modèle de la boîte et passez vos éléments en box-sizing: border-box : les mesures redeviennent prévisibles.
Et Grid, alors ?
Flexbox gère une dimension à la fois : une ligne, ou une colonne, éventuellement repliée avec flex-wrap. Dès qu’on veut contrôler des lignes ET des colonnes en même temps (une vraie grille de page, avec des zones qui s’alignent dans les deux sens), CSS Grid est l’outil prévu pour ça. C’est le prochain guide de cette série. D’ici là, vous avez de quoi faire : les sept propriétés vues ici couvrent l’essentiel de ce qu’on utilise de Flexbox en production, et chaque valeur citée a été vérifiée dans un navigateur avant d’être écrite noir sur blanc.
