Contrôler les proportions des boîtes flexibles le long de l'axe principal
=========================================================================

Dans ce guide, nous verrons les trois propriétés appliquées aux éléments flexibles qui permettent de contrôler leurs tailles et flexibilités le long de l'axe principal : `flex-grow`, `flex-shrink` et `flex-basis`. Comprendre le fonctionnement de ces propriétés est primordial pour maîtriser les boîtes flexibles.

Un premier aperçu
-----------------

Ces trois propriétés contrôlent différents aspects relatifs à la flexibilité des éléments :

* `flex-grow` : quelle proportion de l'espace libre peut-on allouer en supplément à cet élément ?
* `flex-shrink` : quelle proportion de l'espace peut être retirée à cet élément ?
* `flex-basis` : quelle est la taille de l'élément avant tout agrandissement/réduction ?

Ces propriétés sont généralement définies via la propriété raccourcie `flex`. Le code suivant définira `flex-grow` avec la valeur `2`, `flex-shrink` avec la valeur `1` et `flex-basis` avec la valeur `auto`.


```css
.item {
  flex: 2 1 auto;
}
```


Dans l'article sur les concepts de base relatifs aux boîtes flexibles, nous avons pu introduire ces propriétés. Ici, nous les étudierons en profondeur afin de comprendre comment le navigateur les interprète.

Les concepts majeurs relatifs à l'axe principal
-----------------------------------------------

Avant de rentrer dans le détail des propriétés, définissons certains concepts clés qui interviennent lorsqu'on travaille sur les proportions le long de l'axe principal. Ces concepts se basent sur la taille *naturelle* des éléments flexibles (avant tout redimensionnement) et sur la notion d'espace libre.

### Le dimensionnement des objets flexibles

Afin de connaître l'espace disponible pour l'organisation des éléments flexibles, le navigateur doit connaître la taille de l'élément. Comment faire lorsque les éléments ne sont pas dimensionnés avec une largeur ou une hauteur exprimée dans une unité de longueur absolue ?

CSS permet d'utiliser les valeurs `min-content` et `max-content` — ces mots-clés sont définis dans la spécification CSS pour le dimensionnement intrinsèque et extrinsèque et ces valeurs peuvent être utilisées comme unité de longueurs.

Dans l'exemple qui suit, on a deux paragraphes qui contiennent chacun une chaîne de caractères. La largeur du premier paragraphe est `min-content`. Si le navigateur utilisé prend en charge ce mot-clé, on peut voir que le texte passe à la ligne dès que c'est possible, sans dépasser de la boîte. Autrement dit, la longueur `min-content` correspond à la taille du plus grand mot du paragraphe.

Dans le second paragraphe, on utilise la valeur `max-content` et on voit le résultat opposé. Le texte prend autant de place que possible et aucun saut à la ligne supplémentaire n'est introduit. Le texte dépasserait de la boîte si le conteneur était trop étroit.

Si votre navigateur ne prend pas en charge ces mots-clés, les paragraphes seront affichés normalement. La capture d'écran qui suit illustre le résultat obtenu avec un navigateur compatible :

![Le premier paragraphe est aussi large que le plus long mot qu'il contient alors que le second est étendu sur une seule ligne et dépasse.](/fr/docs/Web/CSS/CSS_flexible_box_layout/Controlling_ratios_of_flex_items_along_the_main_axis/ratios-size.png)

Pour la suite de cet article, gardez à l'esprit l'impact de `min-content` et `max-content` lorsque nous verrons les propriétés `flex-grow` et `flex-shrink`.

### Espace libre positif et négatif

Pour étudier ces propriétés, nous devons définir le concept d'**espace libre positif et négatif**. Lorsqu'un conteneur flexible possède un espace libre positif, il dispose de plus d'espace qu'il n'est nécessaire pour afficher les éléments flexibles qu'il contient. Si on a, par exemple, un conteneur dont la largeur mesure 500 pixels, la propriété `flex-direction` qui vaut `row` et trois éléments qui mesurent chacun 100 pixels, il reste alors 200 pixels d'espace libre positif qui pourrait être réparti entre les éléments si on le souhaitait.

![Une image illustrant l'espace restant après que les éléments aient été affichés.](/fr/docs/Web/CSS/CSS_flexible_box_layout/Controlling_ratios_of_flex_items_along_the_main_axis/basics7.png)

L'espace libre négatif est l'espace supplémentaire qui aurait été nécessaire pour contenir tous les éléments à l'intérieur du conteneur flexible. Si on dispose d'un conteneur dont la largeur mesure 500 pixels et trois éléments flexibles dont chacun mesure 200, l'espace total occupé mesure 600 pixels et on a donc 100 pixels d'espace libre négatif. Cet espace pourrait être retiré des éléments afin qu'ils soient contenus dans le conteneur.

![Les objets dépassent du conteneur.](/fr/docs/Web/CSS/CSS_flexible_box_layout/Controlling_ratios_of_flex_items_along_the_main_axis/ratios1.png)

C'est cette distribution de l'espace libre qu'il est nécessaire de comprendre afin d'étudier les différentes propriétés relatives aux propriétés flexibles.

Les exemples étudiés par la suite utilisent la propriété `flex-direction` avec la valeur `row`, ce sera donc leur largeur qui sera leur dimension principale. Vous pouvez modifier les exemples afin d'utiliser `flex-direction: column` (dans ce cas, l'axe principal sera celui des colonnes et la dimension principale sera la hauteur).

La propriété `flex-basis`
-------------------------

La propriété `flex-basis` définit la taille initiale de l'élément flexible avant la répartition de l'espace. La valeur initiale de cette propriété est `auto`. Si `flex-basis` vaut `auto`, le navigateur vérifie si la taille de l'élément est définie de façon absolue et utilise cette valeur pour `flex-basis` (par exemple si on indique dans la feuille de style que l'élément mesure 200 pixels, c'est cette mesure qui sera utilisée comme valeur pour `flex-basis` pour cet élément).

Si la taille initiale de l'élément n'est pas définie de façon absolue, `auto` correspondra à la taille déterminée automatique. C'est là qu'on comprend mieux l'utilité de `min-` et `max-content`, car la boîte flexible utilisera `max-content` comme valeur pour `flex-basis`. Dans l'exemple suivant, nous verrons comment en tirer parti.

Dans cet exemple, on crée un ensemble de boîtes inflexibles avec la valeur `0` pour `flex-grow` et `flex-shrink`. On peut voir comment le premier objet, ayant une largeur explicite de 150 pixels, occupe une `flex-basis` de `150px` tandis que les deux autres objets qui n'ont pas de largeur sont dimensionnés en fonction de la largeur de leur contenu.

En plus du mot-clé `auto`, on peut également utiliser le mot-clé `content` comme valeur pour `flex-basis`. Ainsi, `flex-basis` sera calculée en fonction de la taille du contenu, même s'il y a une largeur explicitement définie sur l'objet. Ce mot-clé est plus récent et est moins largement pris en charge. Toutefois, on peut obtenir le même effet en utilisant le mot-clé `auto` et en s'assurant que l'objet n'a pas de largeur définie, ainsi, le dimensionnement automatique sera effectué en fonction du contenu.

Si on souhaite que la boîte flexible ignore complètement la taille du contenu lors de la répartition de l'espace, on pourra utiliser `flex-basis` avec la valeur `0`. En résumé, cela revient à indiquer que tout l'espace est disponible et peut être réparti proportionnellement. Nous verrons des exemples utilisant cette valeur lorsque nous étudierons `flex-grow`.

La propriété `flex-grow`
------------------------

La propriété `flex-grow` définit **le coefficient d'agrandissement flexible**, qui détermine la façon dont l'objet flexible grandira par rapport aux autres objets flexibles du même conteneur lorsque l'espace libre sera distribué.

Si tous les objets possèdent la même valeur pour le coefficient `flex-grow`, l'espace sera réparti également entre chacun. Dans ce cas, on utilisera généralement la valeur `1`. Ceci étant dit, on pourrait tout aussi bien utiliser la valeur `88`, `100` ou `1.2` — ce coefficient est un simple ratio. Si le coefficient est le même pour tous les objets et qu'il reste de l'espace libre dans le conteneur, cet espace sera réparti équitablement.

### Combiner `flex-grow` et `flex-basis`

Les choses se compliquent lorsque `flex-grow` et `flex-basis` interagissent. Prenons un exemple où trois objets flexibles ont chacun des contenus de longueurs différentes et auxquels on applique la règle suivante :

`flex: 1 1 auto;`

Dans ce cas, `flex-basis` vaut `auto` et les objets n'ont pas de largeur explicite définie : ils sont donc dimensionnés automatiquement. Cela signifie que la boîte flexible utilisera la taille `max-content` des éléments. Après avoir disposé les objets, il reste de l'espace libre dans le conteneur flexible (ce qui correspond à la zone hachurée de la figure suivante) :

![Une image illustrant l'espace libre positif avec une zone hachurée.](/fr/docs/Web/CSS/CSS_flexible_box_layout/Controlling_ratios_of_flex_items_along_the_main_axis/ratios2.png)

On utilise ici une valeur `flex-basis` égale à la taille du contenu, l'espace disponible qui peut être distribué est donc égal à la taille du conteneur (ici sa largeur) moins la taille des éléments. Cet espace est partagé équitablement entre les différents objets. Ainsi, l'objet le plus grand finira avec une taille plus grande, car sa taille de départ est plus importante bien que la même quantité d'espace restant ait été affectée aux autres objets :

![L'espace positif est réparti entre les éléments.](/fr/docs/Web/CSS/CSS_flexible_box_layout/Controlling_ratios_of_flex_items_along_the_main_axis/ratios3.png)

Si on souhaite obtenir trois objets de la même taille alors qu'ils ont des tailles initiales différentes, on pourra utiliser :

`flex: 1 1 0;`

Ici, on indique que, lors de la phase de répartition de l'espace, la taille des objets vaut `0` — tout l'espace peut être utilisé. Or, les trois objets ayant tous le même coefficient `flex-grow`, ils récupèrent chacun la même quantité d'espace. On obtient donc trois objets flexibles de même largeur.

Vous pouvez modifier le coefficient `flex-grow` pour le passer de 1 à 0 dans l'exemple qui suit pour observer la façon dont les objets se comportent :

### Affecter différents coefficients `flex-grow` aux éléments

Notre compréhension du fonctionnement de `flex-grow` avec `flex-basis` nous permet de mieux contrôler chacun des éléments en leur affectant différents coefficients `flex-grow`. Si on conserve la valeur `0` pour `flex-basis` afin que tout l'espace soit distribué, on pourra affecter différentes valeurs de `flex-grow` afin qu'ils grandissent différemment. Dans l'exemple qui suit, on utilise les valeurs suivantes :

* `1` pour le premier élément
* `1` pour le deuxième élément
* `2` pour le troisième

On utilise `flex-basis` avec la valeur `0` ce qui signifie que l'espace disponible est réparti de la façon suivante. On additionne les différents facteurs `flex-grow` puis on divise l'espace libre du conteneur par cette somme (dans notre exemple, elle vaut 4). Ensuite, on répartit l'espace en fonction des différents coefficients individuels : le premier objet récupère une part d'espace, le deuxième en récupère également une et le dernier récupère deux parts. Autrement dit, le troisième objet sera deux fois plus grand que le premier et le deuxième objet.

Rappelons qu'on peut utiliser n'importe quelle valeur positive pour ces facteurs. C'est le rapport entre ces différents facteurs qui importe. Vous pouvez aussi bien utiliser des nombres entiers ou des nombres décimaux. Pour tester cela, vous pouvez changer les coefficients précédents afin de plutôt utiliser respectivement `.25`, `.25` et `.50` — vous obtiendrez alors le même résultat.

La propriété `flex-shrink`
--------------------------

La propriété `flex-shrink` définit **le coefficient de rétrécissement flexible** qui détermine la façon dont l'objet flexible se réduit relatviement aux autres objets du conteneur flexible lorsque l'espace négatif est distribué.

Cette propriété est utilisée lorsque le navigateur calcule les valeurs `flex-basis` des différents objets flexibles et obtient des valeurs qui dépassent la taille du conteneur flexible. Tant que `flex-shrink` possède une valeur positive, les éléments pourront rétrécir afin de ne pas dépasser du conteneur.

Ainsi, si `flex-grow` gère la façon dont on peut ajouter de l'espace disponible, `flex-shrink` gère la façon dont on retire de l'espace aux boîtes des objets afin qu'ils ne dépassent pas de leur conteneur.

Dans le prochain exemple, on dispose de trois éléments dans le conteneur flexible. Chacun mesure 200 pixels de large dans un conteneur qui mesure 500 pixels de large. Si `flex-shrink` vaut `0`, les éléments ne sont pas autorisés à rétrécir et ils dépassent donc de la boîte.

En passant la valeur de `flex-shrink` à `1`, on peut voir que la taille de chaque élément diminue de la même façon afin que l'ensemble des objets tiennent dans la boîte. Les éléments ont désormais une taille inférieure à leur taille initiale.

### Combiner `flex-shrink` et `flex-basis`

On pourrait dire et penser que `flex-shrink` fonctionne de la même façon que `flex-grow`. Toutefois, deux arguments viennent contrecarrer cette analogie.

Le premier, expliqué de façon subtile dans la spécification est la différence de comportement entre `flex-shrink` et l'espace libre négatif et celui de `flex-grow` avec l'espace libre positif :

> 
> "Note : Le coefficient `flex-shrink` est multiplié par la taille de base (`flex-basis`) lors de la distribution de l'espace négatif. Ainsi, l'espace négatif est distribué proportionnellement au rétrécissement possible de l'élément. Autrement dit, un petit élément ne sera pas réduit à une taille nulle avant qu'un plus grand élément n'ait été réduit de façon notable."
> 
> 
> 

Le second argument s'explique par l'impossibilité de réduire les petits éléments à une taille nulle lors de la suppression de l'espace libre négatif. Les éléments seront au maximum rétrécis jusqu'à obtenir leur taille `min-content` — c'est-à-dire la taille qu'ils obtiennent s'ils utilisent tous les emplacements de rupture de ligne possibles.

On peut observer ce seuil avec `min-content` dans l'exemple qui suit où `flex-basis` est résolu avec la taille du contenu. Si on change la largeur du conteneur flexible (en l'augmentant à 700 pixels par exemple) puis en réduisant la largeur de l'élément flexible, on peut voir que les deux premiers objets passent à la ligne. Toutefois, ils ne deviennent pas plus petits que `min-content`. Lorsque la boîte se réduit, l'espace est simplement retiré du troisième élément.

En pratique, cette méthode de rétrécissement fournit des résultats prévisibles, car on ne souhaite pas que le contenu disparaisse entièrement ou que les boîtes soient plus petites que leur contenu minimal. Les règles présentées ci-avant sont donc pertinentes lorsqu'on souhaite rétrécir des objets afin qu'ils rentrent dans un conteneur.

### Utiliser différents coefficients `flex-shrink` pour différents éléments

Comme avec `flex-grow`, on peut utiliser différents coefficients `flex-shrink`. Cela permet de modifier le comportement par défaut et on peut ainsi avoir un élément qui se réduit plus ou moins rapidement que ses voisins (voire qui ne se réduit pas du tout).

Dans l'exemple suivant, le premier objet possède un coefficient `flex-shrink` égal à 1, le deuxième a un coefficient égal à `0` (il ne rétrécira pas du tout) et le troisième est paramétré avec `4`. Ainsi, le troisième élément rétrécit plus vite que le premier. N'hésitez pas à utiliser différentes valeurs pour observer le résultat obtenu. De la même façon qu'avec `flex-grow`, on peut utiliser nombres entiers ou des nombres décimaux, utilisez ce qui vous paraît le plus pertinent.

Maîtriser le dimensionnement des objets flexibles
-------------------------------------------------

Comprendre le dimensionnement des objets flexibles revient avant tout à comprendre les différentes étapes qui sont déroulées et notamment celles-ci que nous avons pu étudier dans ces guides :

### Quelle est la taille de base de l'objet ?

1. Si `flex-basis` vaut `auto` et que l'objet possède une dimension explicitement définie, c'est cette dimension qui sera utilisée.
2. Si `flex-basis` vaut `auto` ou `content` (pour les navigateurs qui prennent en charge cette valeur), c'est la taille du contenu qui déterminera la taille de base de l'élément
3. Si `flex-basis` est exprimée avec une valeur de longueur non nulle, c'est cette valeur qui sera la taille de base de l'élément.
4. Si `flex-basis` vaut `0`, la taille de l'élément n'est pas pris en compte lors de la répartition de l'espace.
### De l'espace est-il disponible ?

Les objets ne s'étendent pas s'il n'y a pas d'espace libre positif et ne se réduisent pas s'il n'y a pas d'espace libre négatif.

1. Si on prend tous les objets et qu'on somme leur dimension principale (la largeur si on travaille en ligne ou la hauteur si on travaille en colonne) et qu'on obtient une quantité inférieure à la dimension principale du conteneur, on aura alors un espace libre positif et c'est la propriété `flex-grow` qui entrera en jeu.
2. Si cette somme dépasse la taille du conteneur flexible, on aura alors un espace libre négatif et c'est la propriété `flex-shrink` qui sera utilisée.
### Les autres façons de distribuer l'espace

Si on ne souhaite pas ajouter d'espace aux objets, on pourra tout aussi bien répartir cet espace libre entre les objets ou autour grâce aux propriétés d'alignement vu dans le guide sur l'alignement. La propriété `justify-content` permettra de répartir cet espace entre les objets ou autour d'eux. Les marges automatiques peuvent être utilisées sur les objets flexibles afin d'absorber l'espace et de créer des gouttières entre ces objets.

Tout ces outils relatifs aux boîtes flexibles vous permettent d'accomplir la plupart des dispositions et n'auront plus de secret au fur et à mesure de vos essais et expérimentations.