Comprendre flex-grow
Sommaire
flex-grow n’est pas une largeur. C’est une part de l’espace restant : tu dis à un élément « prends telle fraction de ce qui dépasse », et le navigateur fait le calcul à ta place. Le jour où ce modèle mental se met en place, la propriété arrête d’être capricieuse — et tu arrêtes de saupoudrer des flex-grow: 1 au hasard en espérant que ça tombe juste.
Le résultat, d’abord#
Voici trois boîtes dans un conteneur display: flex. Aucune n’a de largeur en pixels. Pourtant, celle du milieu occupe deux fois plus de place que ses voisines :
Personne n’a écrit width: 50%. La boîte centrale ne « fait » pas une taille précise : elle reçoit deux parts de l’espace disponible, contre une seule pour chaque voisine. Redimensionne la fenêtre, et les proportions tiennent pendant que les pixels s’adaptent tout seuls.
C’est exactement ce pour quoi flex-grow est fait — et c’est tout ce qu’il fait. Maintenant qu’on a vu où on va, démontons le mécanisme.
flex-grow, c’est quoi une « part » ?#
Le mot important, c’est restant. Un conteneur flex commence par poser la taille de base de chacun de ses enfants — leur La taille d’un élément flex avant distribution de l’espace restant. Sa valeur par défaut, auto, revient à prendre la taille du contenu. . Il additionne ces tailles, les retire de sa propre largeur, et ce qu’il reste — l’espace non encore attribué — c’est ça, et seulement ça, qu’il va distribuer.
flex-grow répond alors à une question : « pour cet espace qui reste, combien de parts veux-tu ? » Une boîte à flex-grow: 2 reçoit deux fois plus de ce surplus qu’une boîte à flex-grow: 1. Une boîte à flex-grow: 0 — la valeur par défaut — n’en réclame aucune et se contente de sa taille de base.
Prenons des chiffres pour rendre ça concret. Imagine un conteneur de 600 px et nos trois boîtes qui, une fois le texte et le padding posés, occupent disons 40 px chacune : 120 px utilisés, il reste 480 px. Avec des parts 1·2·1, le navigateur découpe ce surplus en quatre (1 + 2 + 1) : chaque part vaut 120 px. La boîte du milieu en touche deux (240 px), ses voisines une seule (120 px). Ajoute la taille de base de chacune et tu obtiens 160, 280, 160 — qui font bien 600. Rien de magique : une addition.
Fais varier la part de la boîte du milieu et regarde l’espace se redistribuer en direct :
À 0, la boîte centrale ne grandit plus du tout : tout le surplus part vers les deux voisines, qui valent chacune une part. À 1, les trois se partagent l’espace à parts égales. À 5, la boîte du milieu rafle l’essentiel et écrase ses voisines. À aucun moment tu n’as touché à une largeur en pixels — tu as seulement changé un rapport.
La recette en deux temps#
Le CSS derrière la démo tient en deux lignes. Les boîtes réclament une part chacune ; la centrale lit en plus une variable que le curseur fait bouger :
.demo-flex-grow .box { flex-grow: 1;}.demo-flex-grow .box-grow { flex-grow: var(--flex-grow);}Retiens la chronologie, c’est elle qui débloque tout : d’abord le navigateur pose les tailles de base, ensuite il distribue le reste selon les parts. flex-grow n’agit jamais sur la première étape, uniquement sur la seconde. C’est pour ça qu’il faut parfois aller corriger la taille de base — on y revient plus bas — quand la distribution ne donne pas ce qu’on imaginait.
Le piège du « flex-grow: 1 partout »#
Tu as sûrement déjà fait ça : coller flex-grow: 1 sur tous les enfants d’un flex en espérant un résultat précis, puis te demander pourquoi tout finit identique. Bascule l’interrupteur pour voir le piège en action :
Sur « Proportions 1·2·1 », la boîte du milieu garde ses deux parts. Bascule sur « Toutes à 1 » : tout le monde redevient identique. C’est pour ça que ça ne marchait pas quand tu mettais flex-grow: 1 sur tout — tu ne demandais pas « occupe plus de place », tu demandais « répartis le surplus à parts strictement égales ». Donner la même part à tout le monde, c’est dire au navigateur de ne privilégier personne.
Le vrai levier de proportion, c’est la différence entre les parts. 1 et 2, c’est un rapport de un à deux. 1 et 1, c’est l’égalité. Si tu veux qu’un élément domine, donne-lui une part plus grande que les autres, pas la même.
Quand flex-grow ne fait rien#
Il arrive que tu poses un flex-grow bien senti… et que rien ne bouge. Pas de bug : il n’y a tout simplement rien à distribuer.
Un exemple parlant : mets trois paragraphes de texte dense dans un conteneur flex sans permettre le retour à la ligne. Ils remplissent déjà tout l’espace, voire débordent. Tu peux empiler les flex-grow: 1, rien ne grandira — il n’y a pas de surplus, il y a un déficit. Dans ce cas, le problème est en amont : c’est la taille de base qu’il faut revoir. Réduis le flex-basis, autorise les éléments à rétrécir, et le surplus réapparaît — flex-grow retrouve alors de quoi travailler.
Et flex-shrink, dans tout ça ?#
flex-grow gère le surplus ; son miroir, le La capacité d’un élément flex à rétrécir quand l’espace manque. Par défaut 1 : les éléments acceptent de se réduire pour tenir dans le conteneur. , gère le manque. Quand les boîtes ne tiennent pas, c’est lui qui décide qui se serre et de combien. Les deux ne sont jamais à l’œuvre en même temps : ou bien il reste de la place — flex-grow distribue —, ou bien il en manque — flex-shrink comprime.
Voici la transition qui résume une migration de mise en page très courante : on quitte une largeur figée pour une part souple.
.row > .item { width: 50%; flex-grow: 1;}JS ou CSS : qui calcule les largeurs ?#
La même répartition, codée à la main en JavaScript (écouter le resize, mesurer, recalculer) ou laissée à flex-grow. Même résultat, deux quantités de code très différentes :
Récapitulons#
Reviens à la rangée du début : trois boîtes, une qui prend deux parts, pas un seul pixel codé en dur. Tu sais maintenant pourquoi elle est plus large — pas parce qu’on lui a donné une taille, mais parce qu’on lui a donné une part plus grande de l’espace restant.
Trois réflexes à emporter :
flex-growpartage le surplus, jamais la largeur totale.- Une part plus grande que les autres crée une proportion ; la même part partout crée l’égalité.
- Pas de surplus, pas d’effet : si rien ne bouge, c’est la taille de base qu’il faut regarder.
La prochaine fois que tu veux qu’un élément prenne le reste de la place, tu n’as plus besoin de deviner une largeur. Tu lui donnes une part, et tu laisses le navigateur faire l’arithmétique.