Le petit flexbox illustré

Nantes, le 7 septembre 2015.

Flexbox est un nouveau module d’affichage CSS qui apporte quelques possibilités graphiques jusqu’alors impossibles et qui permet aussi de grandement simplifier les constructions habituelles.

Son principal frein reste le support limité à IE 10+ (pas de souci pour la majorité des autres navigateurs), mais au regard des nouveautés offertes, il est d’ores et déjà intéressant d’en comprendre le fonctionnement et de résoudre certaines problématiques grâce à celui-ci.


Déclencher un affichage flexbox passe par la propriété display.

Flexbox diffère un peu des types d’affichages habituels car le changement va ici non seulement impacter l’élément sélectionné, mais également ses enfants directs.
Ainsi on parlera de flex-container et de flex-items ; et il sera possible de passer des propriétés spécifiques à ces deux composants.

Il sera tout à fait possible aussi qu’un élément soit à la fois un flex-items et un flex-container : autrement dit, les imbrications flexbox sont possibles.

La courbe d’apprentissage du module peut paraître abrupte au premier abord. C’est sans compter les simplifications que permettent des outils comme autoprefixer, qui viennent gommer les historiques de nommages et d’implémentations qui ont été faites.

En effet flexbox en est toujours au stade du brouillon et a déjà subi trois refontes. On peut néanmoins penser qu’après un travail mené depuis plus de six ans, il soit maintenant suffisamment mature ; tout comme le statut actuel (last call) de la spécification et le nombre très faible de tickets encore ouverts le laisse entendre.

Quoi qu’il en soit, au lieu de devoir écrire :

.foo
{
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;
}

il suffira simplement de passer par ce code pour que le post-processeur génère la même chose :

.foo
{
    display: flex;
}

On retrouve alors une courbe d’apprentissage relativement douce, où la principale difficulté reste le nombre de nouveautés. Nous allons donc passer en revue chacune d’elles méthodiquement, en commençant par les propriétés qui peuvent s’appliquer au flex-container.


Retenez cependant avant tout qu’un flex-container ou un flex-item appliquent un contexte de formatage de type flex équivalent au type block. (N’hésitez pas à lire maintenant ou plus tard l’article lié si ce concept ne vous semble pas clair.)

Propriétés sur le flex-container

La direction

flex-direction permet de gérer la direction, par défaut en ligne (row) ; on pourra aussi la passer en colonne (column) très facilement.


La démonstration qui suit fait alterner différents affichages à chaque clic de votre part.
(Il en sera de même sur la plupart des démonstrations de cette page.)


On pourra également inverser les flux et utiliser row-reverse et column-reverse.

Les débordements

flex-wrap permet de gérer les débordements des flex-items dans les lignes ou dans les colonnes.
Bien que par défaut ils ne soient pas autorisés (nowrap), il est tout à fait possible de changer ce comportement avec wrap.

On pourra même inverser le flux et les débordements avec wrap-reverse.

Notez que flex-direction et flex-wrap peuvent s’utiliser conjointement avec la propriété raccourcie flex-flow.

Par exemple :

.bar
{
    flex-direction: column;
    flex-wrap: wrap;
}

sera équivalent à :

.bar
{
    flex-flow: column wrap;
}

La justification sur l’axe principal

justify-content aligne les flex-items le long de l’axe principal.


On parle d’axe principal et d’axe secondaire plutôt que d’axe vertical et horizontal car cela varie en fonction de la direction.


Par défaut les éléments sont empilés en début de flux (flex-start). Ils pourront l’être en fin de flux (flex-end), au milieu (center), espacés entre eux au maximum (space-between) ou espacés chacun d’eux par une marge identique (space-around).


Vous remarquerez quelques petites animations CSS qui permettent de mieux comprendre comment sont effectuées certaines répartitions d’espaces.


La justification sur l’axe secondaire

Les enfants du flex container sont alignés :

  • avec align-items au niveau de chaque ligne ;
  • avec align-content au niveau de l’ensemble des lignes (il en faut donc plusieurs pour en constater l’effet).

align-items prend par défaut la valeur stretch, et accepte également flex-start, flex-end, center et baseline.

align-content prend par défaut la valeur stretch, et accepte également flex-start, flex-end, center, space-between et space-around.

Propriétés sur les flex-items

Passons maintenant aux propriétés qui s’appliquent sur les enfants directs du flex-container et commençons par la plus riche : flex.


Ne confondez pas : nous avons vu plus haut ce mot-clef comme une nouvelle valeur de display ; il s’agit maintenant d’une nouvelle propriété.

Les dimensions

flex est une propriété raccourcie qui combine flex-grow, flex-shrink et flex-basis.

.baz
{
    flex: 0 1 auto;
}

a donc pour équivalent :

.baz
{
    flex-grow: 0;
    flex-shrink: 1;
    flex-basis: auto;
}
  • flex-grow définit les possibilités d’étirements d’un élément,
  • flex-shrink ses possibilités de contractions,
  • et flex-basis sa dimension initiale.

Par étirement et contraction, comprenez par là qu’un élément pourra voir sa taille surchargée afin de répondre au mieux à vos conditions et au contexte d’affichage courant.

flex-grow ne permet pas d’étirement quand il est à 0, il faut passer un nombre positif plus ou moins important pour changer ce comportement par défaut.


Nous expliciterons un peu plus loin (avec flex-basis) la méthode de calcul qui définit les agrandissements.


flex-shrink a pour valeur initiale 1 : la contraction est donc possible par défaut. On pourra lui passer un nombre nul ou un nombre positif pour annuler ou amplifier ce comportement.

Plus un flex-shrink sera important, plus l’élément sera à même d’être compressé.

Comment sont calculées les compressions ?

Lorsque les facteurs de compression sont identiques, les proportions entre les éléments sont conservées.

Dans le prochain exemple la taille du conteneur est revue (et animée) de manière à compresser les flex-items dont les largeurs sont définies en pixels.

On constate une largeur identique entre le premier flex-item et les trois suivants quelle que soit la taille du flex-container.
Et il en va de même pour les largeurs des trois derniers flex-items qui restent identiques.

Vous aurez peut-être noté que la largeur initiale des éléments intervient dans les calculs. Ainsi un élément deux fois plus large qu’un autre (et pourtant le même facteur de compression) se verra proportionnellement deux fois plus compressé si nécessaire.

Quand les facteurs de compression sont différents, l’espace retiré lors de la compression est aussi proportionnel au facteur de compression.

On constate ici que l’espace retiré du dernier flex-item est trois fois plus grand que sur le second ; ainsi que deux fois plus grand que sur le troisième.
Aucun espace n’est par contre retiré du premier.

Ce sont donc les facteurs de compressions et les tailles initiales des éléments qui influent sur le taux de compression possible de chacun.

flex-basis est une propriété qui hérite par défaut (avec la valeur auto) de la largeur (width) ou de la hauteur (height) d’un élément, et ce en fonction de la direction définie sur le flex-container.

Elle peut aussi prendre une valeur qui viendra surcharger cette dimension.

flex-basis va également redéfinir la taille minimale d’un élément (min-width ou min-height) et faire passer sa valeur par défaut de 0 à auto.

On peut ainsi définir un flex-basis à 0, tout en conservant visuellement une taille minimale pour l’élément.

Comment sont calculés les agrandissements ?

Ce qui est très intéressant avec flex-basis, c’est qu’il entre en jeu pour les calculs de dimensionnement : sa valeur va donc considérablement influencer les comportements d’agrandissement.

  • Quand flex-basis est à 0, c’est la taille des flex-items qui sera revue ;
  • quand flex-basis est à auto, c’est l’espace restant qui sera revu.

La justification sur l’axe secondaire

align-items (que nous avons vu plus haut) permet de justifier tous les éléments au sein d’un conteneur.

align-self permet de cibler individuellement ses enfants.

Par défaut il est à auto et hérite du comportement du flex-container mais on retrouve les même valeurs possibles que pour align-items. À savoir : flex-start, flex-end, center, baseline et stretch.

L’ordonnancement

order accepte uniquement des nombres entiers (négatifs ou positifs) et permet d’ordonner les éléments dans le flux. Il est fixé à 0 par défaut.

Les ordres qui sont appliqués aux éléments sont alors classés par ordre croissant et c’est tout le flux d’affichage qui peut s’en retrouver modifié.


Outre cette compréhension basique des propriétés, il faudra bien sûr à l’avenir mieux appréhender l’utilisation de ce nouveau module. Agencements de propriétés, dégradations possibles, bugs…

Par bien des aspects, je trouve que flexbox mélange les avantages des flottants et les avantages des tableaux. Nul doute : si vous êtes amenés à travailler dans des contextes responsifs, les possibilités offertes par flexbox vous intéresseront.


Voici pour compléter une liste de liens sur le sujet :

Bonnes lectures et bonnes expérimentations à tous.

Vincent.

7 commentaires.

  • Marie Guillaumet , le 10 septembre 2015.

    Superbe boulot, Vincent !

    Cela va m’être hyper utile pour comprendre rapidement tous ces concepts nouveaux, que je n’ai pas encore l’habitude de manier (coucou IE9 !).

    Mention spéciale pour les démos, vraiment bien pensées.

    On a de la chance d’avoir des gens comme toi dans cette communauté :)

  • Vincent , le 10 septembre 2015.

    Merci Marie ! blush

  • Webarranco , le 11 septembre 2015.

    Merci beaucoup pour cet article !

    Flexbox on en parle beaucoup, mais il est pas toujours clair et bien expliqué, on dit avant tout qu’il est génial avant de dire comment il marche parfois.

    Super idée les démos, ça donne envie de s’y mettre du coup :)

  • Delphine , le 11 septembre 2015.

    Merci Vincent,
    Tu m’enlèves le brouillard qui planait sur tout ça !

  • Alex , le 12 septembre 2015.

    Merci d’avoir partager ton savoir de manière aussi limpide et concise
    le code css compilé est aussi très instructif
    très interessant

  • STPo , le 14 septembre 2015.

    Vous êtes formidable.

  • Anne-Sophie , le 2 novembre 2015.

    Bonjour bonjour,

    Juste pour dire que cet article est devenu ma page d’accueil le temps d’une refonte d’un site :) Merci !

Laisser un commentaire