4. Mise en page

Dimensionner un élément

Les éléments block et inline-block possèdent des propriétés width et height, permettant d'en spécifier respectivement la largeur et la hauteur, le plus souvent en pixels ou pourcents.

Lorsqu'une de ces propriétés est renseignée avec une valeur en pourcents (%), celle-ci correspondra au pourcentage d'espace que doit prendre l'élément dans son parent. Par exemple la règle width:50% fera occuper à un élément la moitié de la largeur de son parent.

La valeur par défaut pour width et height est "auto", signifiant :

→ pour un block, qu'il utilisera toute la largeur disponible dans son conteneur et ajustera sa hauteur à son propre contenu

→ pour un élément inline-block, que sa largeur comme sa hauteur seront ajustées à son contenu.

Il est également possible pour chaque dimension d'un élément de préserver le comportement "auto" jusqu'à un certain seuil, en ne définissant pas les propriétés width ou height mais leurs variantes min-width, min-height, max-width ou max-height.

Par exemple, pour un élément avec min-width:300px, la largeur sera conditionnée par son propre contenu et l'espace disponible dans son parent. Mais dans le cas où cet espace est inférieur à 300 pixels, l'élément conservera une largeur de 300 pixels. À l'inverse, avec max-width:300px, la largeur de l'élément pourra augmenter en fonction de son contenu, dans les limites de l'espace disponible dans son parent, jusqu'à occuper 300 pixels.

Gestion du débordement

Lorsque des dimensions sont spécifiées pour un élément, il ne s'adaptera plus à son contenu. Il pourra alors arriver que ce dernier doive occuper un volume supérieur à celui disponible dans l'élément, ce qui occasionnera un débordement. Par défaut, le contenu débordant de l'élément est visible.

Ce texte est contenu dans un élément
<div style = "height:70px"></div>
(délimité par la bordure). On constate un débordement, affiché en-dessous de l'élément div suivant.

Ce comportement est modifiable, via la propriété overflow de l'élément conteneur. La valeur par défaut est "visible", elle peut être définie à "hidden" pour tronquer le contenu débordant, "scroll" pour y adjoindre des barres de défilement, ou "auto", ne les ajoutant qu'en cas de besoin.

Avec pour l'élément div
height:70px; overflow:hidden;
on constate que le débordement du texte est tronqué.
Avec pour l'élément div
height:100px; overflow:auto;
on constate que le débordement du texte est tronqué mais qu'une barre de défilement est en place. Cette valeur est à privilégier par rapport à "scroll", qui ajoute systématiquement les deux barres, comme dans l'élément suivant :
height:100px; overflow:scroll;

Note : Les deux axes peuvent également être gérés indépendamment, en utilisant les propriétés overflow-x et overflow-y.

Unités relatives au viewport

Outre le pixel et le pourcent, d'autres unités sont admises pour les propriétés de dimensions. Parmi les plus utiles on trouvera vw, vh, vmin et vmax, dont l'intérêt est de toujours rester relatives aux dimensions de la fenêtre (le "viewport").

Ces unités fonctionneront comme des pourcentages : width:10vw sera équivalent à 10% de la largeur du viewport, height:10vh à 10% de sa hauteur.

Conserver un rapport aux dimensions de la fenêtre s'avèrera utile dès lors que l'on souhaite respecter les principes du design fluide. Ces unités le permettent pour des éléments ne se trouvant ni directement à la racine du document, ni dans un parent ayant lui-même conservé un rapport aux dimensions de la fenêtre.

Une valeur en vh peut être donnée en propriété width, et inversement une valeur en vw peut être donnée en propriété height. Cela permettra notamment d'obtenir facilement des éléments carrés. Par exemple :

/* CSS : */

.carre { display:inline-block; width:25vw; height:25vw; }

<!-- HTML : -->

<div class = "carre"></div>
<div class = "carre"></div>
<div class = "carre"></div>
<div class = "carre"></div>

→ On obtiendra ici une ligne de quatre éléments carrés "fluides", occupant chacun 1/4 de la largeur de la fenêtre.

Les unités vmin et vmax permettent de se référer à l'une ou l'autre des dimensions de la fenêtre, selon laquelle est la plus petite (pour vmin) ou la plus grande (pour vmax).

#element { width:100vmin; height:100vmin; }

→ Cet élément sera un carré, dont les côtés équivaudront à la plus petite des dimensions du viewport : sa largeur pour une fenêtre en orientation "portrait", sa hauteur pour une orientation "paysage". Il restera dans tous les cas correctement dimensionné pour "tenir dans la fenêtre", et être affiché en entier.

Placer les éléments

Par défaut, un élément est placé par rapport à ce qui le précède ou le contient. On utilisera des imbrications d'éléments pour structurer la page, et il faudra réfléchir en termes de conteneurs, parfois successifs.

Aux premiers niveaux de l'arborescence, on peut par exemple répartir l'espace de la page via un système de lignes et colonnes, pouvant mutuellement se contenir. Un élément block adoptera naturellement le comportement d'une ligne, et pourra également contenir des éléments inline-block se répartissant l'espace horizontal disponible comme des colonnes.

Cette idée est illustrée dans l'exemple suivant, avec deux simples classes, pour des éléments conteneurs occupant chacun la moitié de son parent.

div.ligne-demi { height:25%; }
/* et implicitement display:block ; width:100% */

div.colonne-demi { display:inline-block; width:50%; height:100% }
.ligne-demi
.ligne-demi
.colonne-demi
.colonne-demi
.colonne-demi
.colonne-demi
.colonne-demi
.colonne-demi
.colonne-demi
.ligne-demi
.ligne-demi
.colonne-demi
.colonne-demi
.colonne-demi
.colonne-demi
.ligne-demi

Note : le comportement des colonnes se suivant horizontalement peut également être obtenu sur un élément bloc, en le rendant "flottant" via la propriété float. Lorsqu'on spécifie par exemple pour un élément float:left, il se positionnera le plus à gauche possible de son parent, à la suite des éventuels autres éléments flottants qui s'y trouveraient.

Cette technique présente plusieurs inconvénients et aspects contre-intuitifs, notamment l'interaction spatiale avec les éléments voisins non-flottants, et la nécessité de rétablir explicitement le flux normal (vertical) du document après un ou plusieurs éléments flottants, via la présence d'un élément portant la propriété clear:both.

L'idée d'une structure fluide, où toute la largeur de la fenêtre est constamment utilisée, peut présenter des limites au-delà d'un certain espace disponible. Dans une fenêtre trop large, on constatera entre autres des paragraphes aux lignes étirées (donc inconfortables à lire), des images surdimensionnées, des espaces morts inutilement importants...

Une bonne pratique pour contrôler ce problème, consiste à prévoir un conteneur global, fixant une largeur à ne pas dépasser. On limite en fait la page à une colonne, occupant toute la fenêtre par défaut, et se "détachant" d'elle (à un bord ou les deux) lorsque trop large.

#conteneur-global {
  max-width:1200px;
  margin-left:auto; margin-right:auto;
}

→ Placer cet élément au premier niveau de l'arborescence et le faire contenir la suite de la structure permettra par exemple que celle-ci ne dépasse pas 1200 pixels de large, et reste centrée dans la fenêtre (grâce aux deux marges latérales "auto") lorsque celle-ci dépasse ce seuil.

Espacer les éléments

Une fois l'espace de la page subdivisé via les premiers niveaux de conteneurs, il faudra gérer harmonieusement la manière dont de nouveaux éléments s'y placeront. À cette étape, on affine en quelque sorte le "cadre" pour les contenus de la page, principalement en ménageant des espaces vides entre eux, nécessaires à une bonne lisibilité.

C'est ici que les marges internes et externes jouent un rôle important. Elles vont permettre d'ajuster, pour chaque subdivison de l'espace de la page, le retrait des éléments contenus par rapport aux bords de leur conteneur.

Dans la structure suivante par exemple, des contenus sont placés dans des conteneurs sans marges :


.conteneur-bloc {height:33.33%;}

.colonne {display:inline-block;}

.colonne.largeur-1-3 {width:33.33%;}

.colonne.largeur-2-3 {width:66.66%;}

.colonne.largeur-1-2 {width:50%;}

.colonne.largeur-1-4 {width:25%;}

.colonne.boite {
  height:100%; box-sizing:border-box; border:3px solid #006666;
}


<!-- Structure HTML (sans contenus) : -->

<div class = "conteneur-bloc">

  <div class = "colonne boite largeur1-3"></div>
  <div class = "colonne largeur2-3"></div>

</div>

<div class = "conteneur-bloc">

  <div class = "colonne largeur1-2"></div>
  <div class = "colonne largeur1-2"></div>

</div>

<div class = "conteneur-bloc">

  <div class = "colonne largeur1-4"></div>
  <div class = "colonne boite largeur1-4"></div>
  <div class = "colonne largeur1-4"></div>
  <div class = "colonne boite largeur1-4"></div>

</div>

On constate aisément le manque d'aération de l'ensemble :

Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad supercilia fluminis Rheni, resistente multitudine Alamanna pontem suspendere navium conpage Romani vi nimia vetabantur ritu grandinis undique convolantibus telis.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad supercilia fluminis Rheni, resistente multitudine Alamanna pontem suspendere navium conpage Romani vi nimia vetabantur ritu grandinis undique convolantibus telis.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad supercilia fluminis Rheni, resistente multitudine Alamanna pontem suspendere navium conpage Romani vi nimia vetabantur ritu grandinis undique convolantibus telis.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad.

En ajoutant des marges externes aux conteneurs, la mise en page gagne en clarté. Cela oblige par contre à tenir compte des marges dans le dimensionnement des conteneurs, pour que l'addition des pourcentages reste juste :


/* On retire à chaque dimension 2x la marge donnée à l'élément */

.conteneur-bloc {height:31.33%; margin:1%;}

.colonne {display:inline-block; margin:1%;}

.colonne.largeur-1-3 {width:31.33%;}

.colonne.largeur-2-3 {width:64.66%;}

.colonne.largeur-1-2 {width:48%;}

.colonne.largeur-1-4 {width:23%;}

.colonne.boite {
  height:98%; box-sizing:border-box; border:3px solid #006666;
}

Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad supercilia fluminis Rheni, resistente multitudine Alamanna pontem suspendere navium conpage Romani vi nimia vetabantur ritu grandinis undique convolantibus telis.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad supercilia fluminis Rheni, resistente multitudine Alamanna pontem suspendere navium conpage Romani vi nimia vetabantur ritu grandinis undique convolantibus telis.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad supercilia fluminis Rheni, resistente multitudine Alamanna pontem suspendere navium conpage Romani vi nimia vetabantur ritu grandinis undique convolantibus telis.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad.

On constate également un problème avec la classe .boite : lorsque ces éléments cherchent à occuper la pleine hauteur de leur parent, l'addition avec les marges ne semble pas juste. Pour éviter les conflits de ce type, on peut opérer de manière à ne pas interférer sur le découpage initial de l'espace, mais en le prenant simplement comme base.

On utilisera pour cela les marges internes, qui à condition que l'élément ait comme propriété box-sizing:border-box, ne s'additionneront pas aux dimensions définies pour lui. Les enfants de cet élément pourront ensuite occuper sans problème ses pleines largeur et hauteur, desquelles le padding sera automatiquement déduit.


.conteneur-bloc , . colonne {box-sizing:border-box; padding:1%;}

.conteneur-bloc {height:33.33%;}

.colonne {display:inline-block;}

.colonne.largeur-1-3 {width:33.33%;}

.colonne.largeur-2-3 {width:66.66%;}

.colonne.largeur-1-2 {width:50%;}

.colonne.largeur-1-4 {width:25%;}

/* La boite n'est plus une classe pour une colonne, mais un élément supplémentaire à y insérer */

.colonne.pleine-hauteur {height:100%;}

.boite {
  height:100%; box-sizing:border-box; border: 3px solid #006666;
}


<!-- Structure HTML (sans contenus) : -->

<div class = "conteneur-bloc">

  <div class = "colonne largeur1-3 pleine-hauteur">
      <div class = "boite"></div>
  </div>

  <div class = "colonne largeur2-3"></div>

</div>

<div class = "conteneur-bloc">

  <div class = "colonne largeur1-2"></div>

  <div class = "colonne largeur1-2"></div>

</div>

<div class = "conteneur-bloc">

  <div class = "colonne largeur1-4"></div>

  <div class = "colonne largeur1-4 pleine-hauteur">
      <div class = "boite"></div>
  </div>

  <div class = "colonne largeur1-4"></div>

  <div class = "colonne largeur1-4 pleine-hauteur">
      <div class = "boite"></div>
  </div>

</div>
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad supercilia fluminis Rheni, resistente multitudine Alamanna pontem suspendere navium conpage Romani vi nimia vetabantur ritu grandinis undique convolantibus telis.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad supercilia fluminis Rheni, resistente multitudine Alamanna pontem suspendere navium conpage Romani vi nimia vetabantur ritu grandinis undique convolantibus telis.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad supercilia fluminis Rheni, resistente multitudine Alamanna pontem suspendere navium conpage Romani vi nimia vetabantur ritu grandinis undique convolantibus telis.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad.
Emensis itaque difficultatibus multis et nive obrutis callibus plurimis ubi prope Rauracum ventum est ad.

Cette méthode permet également, dans une structure de base fluide, de "stabiliser" en quelque sorte les marges, en ré-insérant des valeurs non relatives au viewport ni à un conteneur global, par exemple en pixels. En utilisant les marges externes, il aurait été difficile de déduire ces valeurs en pixels de dimensions en pourcents.


.conteneur-bloc , . colonne {box-sizing:border-box; padding:20px;}

/* Le reste ne change pas */

.conteneur-bloc {height:33.33%;}

.colonne {display:inline-block;}

.colonne.largeur-1-3 {width:33.33%;}

.colonne.largeur-2-3 {width:66.66%;}

.colonne.largeur-1-2 {width:50%;}

.colonne.largeur-1-4 {width:25%;}

.colonne.pleine-hauteur {height:100%;}

.boite {
  height:100%; box-sizing:border-box; border: 3px solid #006666;
}

Positionnement absolu

En termes d'occupation d'espace dans le document, nous avons vu que par défaut un élément est tributaire de ses voisins ; le "flux" de la page veut que les éléments (frères) soient placés à la suite, de haut en bas et de gauche à droite.

Il est toutefois possible de "sortir" de ce flux, en donnant aux éléments un positionnement absolu. Il deviendra possible de spécifier pour chacun des coordonnées, qui le placeront librement, et indépendamment de ses frères, sur un plan en deux dimensions.

→ Un élément porteur de la propriété position:absolute acceptera de nouvelles propriétés left, top, right et bottom, pouvant être déclarées dans toutes les unités de mesures acceptées en CSS : pixels, pourcents, etc. Ces propriétés utiliseront comme références (ou points "zero") les bords de l'élément parent. Un élément absolu pour lequel on spécifie par exemple left:30px verra son bord gauche placé à 30 pixels du bord gauche de son parent.

→ Un élément en position absolue perdra son éventuel comportement bloc ; par défaut il ne prendra pas la largeur de son parent mais s'adaptera à son propre contenu. Il reste bien sûr dimensionnable via width et height. Par ailleurs, un élément pour lequel on spécifie par exemple left:50px; right:100px sera dimensionné en fonction des positions respectives de ses bords gauche et droit. De cette manière, top:0; left:0; height:100%; width:100% équivaudra à top:0; left:0; bottom:0; right:0.

→ La sortie du flux implique qu'un élément en position absolue n'influera plus sur la disposition de ses frères : ni ses dimensions, ni ses marges externes ne pousseront le reste du contenu de son parent. Ce dernier n'en tiendra pas non plus compte dans son propre dimensionnement.

→ Si un élément en position absolue est placé à la suite d'éléments non absolus, et qu'aucune coordonnée (top, left, right, bottom) n'a été spécifiée pour lui, il sera placé naturellement à la suite de l'élément précédent (mais "n'existera" toujours pas dans le flux de la page : l'élément non-absolu suivant sera placé au même endroit, et on constatera une superposition des deux).

ATTENTION : un élément ne peut servir de référence absolue à un autre (son enfant) que s'il est lui-même en position absolue (ou ses variantes "fixe" ou "relative", voir ci-dessous). Lorsqu'on positionne de manière absolue un élément dans un parent pour lequel aucune propriété position n'est définie, l'élément absolu prendra comme référence la fenêtre et non son élément parent.

→ Dans le cas où l'on a besoin de contenir des éléments absolus dans un élément devant lui-même rester inclus dans le flux de la page (donc pour lequel un positionnement absolu n'est pas une bonne option), on pourra donner à ce parent une position:relative. Celle-ci combinera, en quelque sorte, les comportements bloc / inline (pour le placement du parent dans la page) et position:absolute (pour ce qui est admis au sein de ce parent).

→ Lorsqu'un élément possède la propriété position:relative, lui attribuer des valeurs pour top, left, right ou bottom le sortiront du flux de la page. Mais à la différence d'un positionnement absolu, ces coordonnées prendront comme référence l'emplacement naturel de l'élément plutôt que les bords de son parent. Par exemple, un élément en position relative avec top:100px se retrouvera 100 pixels en-dessous de sa position normale dans le flux. Cela agit en quelque sorte comme une marge externe, qui ne décalerait pas les éléments suivants.

Une troisième valeur est admise pour la propriété position, permettant de "fixer" des éléments par rapport à la fenêtre. Dans ce cas l'imbrication des éléments dans un éventuel parent n'est pas prise en compte.

→ Un élément avec position:fixed ne suivra pas la page lorsque l'utilisateur la fera défiler. Dans ce cas par exemple, bottom:0 résultera en un élément se trouvant toujours accolé au bas de la fenêtre, quelle que soit la position dans le défilement de la page. Par ailleurs, si un élément fixe déborde de la page, il n'occasionnera pas de lui-même la possibilité de faire défiler celle-ci.

→ En-dehors de ces distinctions, un élément fixe se comportera comme avec un positionnement absolu concernant son placement et son dimensionnement. Il peut également sans problème servir de parent à des éléments en position absolue.

Les éléments positionnés (absolus, relatifs ou fixes) peuvent se superposer. Par défaut, un élément positionné sera affiché "par-dessus" le flux de la page, et l'ordre dans lequel des éléments positionnés seront superposés entre eux dépend de leur ordre d'apparition dans la structure HTML : le plus bas dans la page sera affiché le plus "à l'avant".

Dans le cas où il est nécessaire de s'affranchir de cette logique (lorsqu'un élément positionné doit être affiché devant un autre se trouvant pourtant après lui dans la structure de la page), la propriété z-index peut être utilisée pour spécifier un ordre de profondeur sur l'axe Z.

Par défaut, un élément possède un z-index de 0 ; plus la valeur (un nombre entier) renseignée est importante, plus l'élément sera placé en avant. Pour deux éléments avec le même z-index, c'est à nouveau leur ordre d'apparition dans le HTML qui les départagera.

Note : Lorsqu'aucune valeur n'est renseignée pour la propriété position d'un élément (cas par défaut), on parlera de position:static.

Le modèle Flexbox

L'approche Flexbox permet de gérer la répartition et l'alignement, sur les deux axes, d'un ensemble d'éléments dans un conteneur. Selon ce modèle, les éléments enfants sont en quelque sorte "conscients" les uns des autres : leurs dimensions et dispositions ne seront pas forcément figées mais prendront intelligemment en compte les variations d'espace disponible pour obtenir des lignes et colonnes cohérentes.

La logique diffère quelque peu de celle vue plus haut (lignes et colonnes via éléments inline et block), mais ce modèle s'avère très pratique et correspond bien à une approche moderne du design web moderne.

→ Pour mettre en pratique ce modèle, il faut tout d'abord spécifier pour le conteneur la propriété display:flex, ce qui conditionnera le comportement de ses enfants (sauf éléments absolus / fixes). Le conteneur en lui-même prendra les proriétés d'un élément block vis-à-vis de sa propre disposition dans le flux, sauf s'il est positionné de manière absolue ou fixe.

Les éléments enfants adopteront par défaut, en termes de dimensionnement, un comportement rappelant celui d'un inline-block.

→ Il s'agit ensuite de déterminer l'orientation dans le conteneur, c'est-à-dire quel axe doit être considéré comme principal. Par défaut il s'agit de l'axe horizontal, ce qui correspond à la propriété flex-direction:row et se traduit par une répartition horizontale des éléments enfants. En spécifiant flex-direction:column la répartition sera verticale.

Par défaut la répartition prend comme point d'origine le coin supérieur gauche du conteneur. On peut obtenir une ligne débutant à droite via flex-direction:row-reverse et une colonne débutant en bas via flex-direction:column-reverse.

La répartition et l'alignement des éléments enfants se spécifie pour chacun des deux axes via les propriétés justify-content (axe principal) et align-items (l'axe secondaire). Les valeurs acceptées pour ces deux propriétés sont flex-start pour un regroupement en début d'axe (valeur par défaut pour l'axe principal), flex-end pour un regroupement en fin d'axe, et center pour un regroupement au centre.

→ Pour l'axe secondaire (propriété align-items), la valeur stretch est également admise, et amènera les éléments enfants (non dimensionnés par ailleurs) à s'étirer pour occuper tout l'espace disponible sur l'axe. Il s'agit du comportement par défaut.

→ Pour l'axe principal (propriété justify-content), d'autres valeurs sont acceptées et permettent la distribution (gestion de l'espacement) des éléments enfants. Il s'agit de space-between (répartition équitable entre les éléments, pas d'espace à l'extérieur), space-around (ajout d'un demi-espace en début et fin) et space-evenly (ajout d'un espace entier en début et fin).

→ Par défaut tous les éléments enfants sont disposés sur une seule et même ligne ou colonne (selon l'axe défini comme principal). Lorsque l'espace disponible est insuffisant, cela occasionnera un débordement par rapport au conteneur. Pour forcer un "retour à la ligne" / "à la colonne", la propriété flex-wrap peut être utilisée, avec la valeur wrap. La valeur par défaut est nowrap, et une troisième valeur wrap-reverse est admise pour inverser le sens dans lequel les nouvelles lignes ou colonnes seront ajoutées.

Lorsque les éléments enfants sont répartis sur plusieurs lignes ou colonnes via flex-wrap, une propriété supplémentaire permet de gérer la distribution de celles-ci : align-content, acceptant toutes les valeurs évoquées ci-dessus pour justify-content et align-items. Par défaut sa valeur est stretch.

Les propriétés précédentes sont à appliquer au conteneur pour gérer le comportement global de ses éléments enfants. Mais ces derniers peuvent recevoir des propriétés complémentaires, permettant de spécifier intelligemment leurs dimensions en tenant compte de leur cohabitation. Si pour un élément flexible les propriétés width, height, etc. sont admises, elles peuvent dans certains cas s'avérer trop "figées". On privilégiera alors les propriétés plus spécifiques flex-basis, flex-grow et flex-shrink (que l'on pourra également rencontrer sous la forme condensée flex), permettant d'intégrer la notion de rapport entre les éléments.

flex-basis est utilisée pour spécifier la dimension initiale de l'élément sur l'axe principal (respectée lorsqu'assez d'espace est disponible). Cette propriété, nécessitant comme valeur une mesure (pixels, pourcents, etc) peut sembler similaire à width ou height, mais son avantage est la prise en compte des deux suivantes.

flex-grow permet de définir jusqu'à quel point l'élément peut s'étendre lorsque de l'espace est disponible sur l'axe principal. La valeur attendue est un nombre entier positif, exprimant la proportion de l'élément par rapport à ses voisins, c'est-à-dire quelle part maximale de l'espace il est autorisé à occuper. Par exemple, un élément avec flex-grow:2 pourra occuper deux fois l'espace autorisé pour un éventuel voisin avec flex-grow:1.

flex-shrink, à l'inverse, permet de définir jusqu'à quel point l'élément peut se rétrécir lorsque l'espace disponible sur l'axe principal est réduit. La valeur attendue est également un nombre entier positif exprimant une proportion ; dans ce cas il s'agira de la part minimale de l'espace du conteneur que l'élément doit occuper.

Il est tout à fait admis d'imbriquer un conteneur flex dans un autre conteneur flex, ce qui permet au final un très vaste éventail de possibilités en termes de mise en page en utilisant ce modèle.