Try   HackMD

La Mise en Page Avec Flexbox

Afin d'enrichir l'expérience de ce cours, je vous invite à réaliser des tests en direct live. Faites un saut sur code-pen.io, let's go !

Un conteneur, des éléments

Comme nous le savons, la plupart des boîtes sont de type block

Comportement par défaut avec des éléments de type block

Au début, les devs utilisaient des tableaux HTML pour faire la mise en page.

Puis, CSS est apparu et on a commencé à faire une mise en page à l'aide de la propriété inline-block.

Une autre, plus pratique, a consisté à créer des éléments de type float sur la page.

Aujourd'hui, de meilleures techniques existent et voici l'une d'entre elles : flex-box !

Flex-box est reconnu par tous les navigateurs récents !


Utiliser flex-Box

Notez le code html suivant :

HTML

<div id="parent"> <div class="enfant"></div> <div class="enfant"></div> <div class="enfant"></div> </div>

CSS

#parent
{
​   display: flex;
}

display: flex sur le conteneur parent

C'est ainsi qu'on définit un "container flex", il est block par défaut (ou inline selon la valeur donnée).

Cela crée un contexte flex pour tous les descendants directs du conteneur parent.

display: <flex>;

La valeur flex génère un conteneur flex. Il peut maintenant agir sur les "éléments flex" (éléments enfants) qui sont à l'intérieur de ce conteneur.

flex-direction : disposer les éléments enfants en ligne ou en colonne

Grâce à la propriété display: flex sur le conteneur parents nous pouvons agencer ces éléments enfants dans le sens que l'on veut.

Avec flex-direction, on peut les positionner verticalement ou encore les inverser. Il peut prendre les valeurs suivantes :

  • row : organisés sur une ligne (par défaut)
  • column : organisés sur une colonne
  • row-reverse : organisés sur une ligne, mais en ordre inversé
  • column-reverse : organisés sur une colonne, mais en ordre inversé

Exemple :

#parent
{
    display: flex;
    flex-direction: column;
}

Notez que les éléments enfants sont placés en ligne par défaut car la propriété flex-direction: row est activée par défaut.
Encore plus important, si vous ne définissez pas de largeur ou de hauteur, c'est le navigateur qui recalcule la taille des éléments enfants.
Les enfants seront étirés (stretch) pour couvrir tout l'espace disponible.
Pensez toujours à vérifier les valeurs calculées à l'aide de l'outil développeur.

Maintenant que le conteneur parent est flex, il y a tout un tas d'autres propriétés utiles que nous allons voir juste après.

Essayez aussi de tester l'ordre inverse pour voir :

#parent
{
    display: flex;
    flex-direction: column-reverse;
}

La différence : les blocs enfants sont maintenant dans l'ordre inverse ! Je n'ai pas du tout changé le code HTML qui reste le même depuis le début.

wrap : le retour à la ligne des éléments enfants

Par défaut, les blocs enfants essaient de rester sur la même ligne s'ils n'ont pas la place (ce qui peut provoquer des bugs de design parfois).

Si vous voulez, vous pouvez demander à ce que les blocs enfants aillent à la ligne lorsqu'ils n'ont plus la place avec flex-wrap qui peut prendre ces valeurs :

  • nowrap : pas de retour à la ligne (par défaut)
  • wrap : les éléments vont à la ligne lorsqu'il n'y a plus la place
  • wrap-reverse : les éléments vont à la ligne lorsqu'il n'y a plus la place en sens inverse

Exemple :

#parent
{
    display: flex;
    flex-wrap: wrap;
}

Voici l'effet que prennent les différentes valeurs sur une même illustration :

justify-content : aligner les éléments enfants sur l'axe principal

Pour faire simple, partons sur des éléments organisés horizontalement (c'est le cas par défaut).

Pour changer leur alignement, on va utiliser justify-content , qui peut prendre ces valeurs :

  • flex-start : alignés au début (par défaut)
  • flex-end : alignés à la fin
  • center : alignés au centre
  • space-between : les éléments sont étirés sur tout l'axe (il y a de l'espace entre eux)
  • space-around : idem, les éléments sont étirés sur tout l'axe, mais ils laissent aussi de l'espace sur les extrémités

Par exemple :

#parent
{
    display: flex;
    justify-content: space-around;
}

#parent
{
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: 350px; /* hauteur pour que les éléments aient la place de bouger */
}

align-items : aligner les éléments enfants sur l'axe secondaire

Comme je vous disais, si nos éléments enfants sont placés dans une direction horizontale (ligne), l'axe secondaire est vertical.

Et inversement, si nos éléments enfants sont dans une direction verticale (colonne), l'axe secondaire est horizontal.

Avec align-items , nous pouvons changer leur alignement sur l'axe secondaire.

Les enfants vont s'aligner les uns par rapport aux autres sur l'axe secondaire.

La propriété peut prendre ces valeurs :

  • stretch : les éléments sont étirés sur tout l'axe (valeur par défaut)
  • flex-start : alignés au début
  • flex-end : alignés à la fin
  • center : alignés au centre
  • baseline : alignés sur la ligne de base (Voir Article 1 et Article 2)

Pour ces exemples, nous allons partir du principe que nos éléments enfants sont dans une direction horizontale (mais n'hésitez pas à tester aussi dans la direction verticale !).

#parent
{
    display: flex;
    justify-content: center;
    align-items: center;
}

Génial, voyez maintenant comme il simple de centrer verticalement et horizontalement.

Il est possible de faire une exception pour un seul des éléments sur l'axe secondaire avec align-self :

#parent
{
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

.enfant:nth-child(2) /* On prend le deuxième bloc élément */
{
    background-color: blue;
    align-self: flex-end; /* Seul ce bloc sera aligné à la fin */
}

/* ... */

Résultat :

align-content : répartir plusieurs lignes

Si vous avez plusieurs lignes dans votre Flexbox, vous pouvez choisir comment celles-ci seront réparties avec align-content sur l’axe secondaire.

Cette propriété n'a aucun effet s'il n'y a qu'une seule ligne dans la Flexbox.

Prenons donc un cas de figure où nous avons plusieurs lignes.

Je vais rajouter des éléments :

<div id="parent">
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
    <div class="enfant"></div>
</div>

J'autorise mes éléments à aller à la ligne avec flex-wrap :

#parent
{
    display: flex;
    flex-wrap: wrap;
}

Jusque-là, rien de vraiment nouveau.

Voyons voir comment les lignes se répartissent différemment avec la nouvelle propriété align-content que je voulais vous présenter.

Elle peut prendre ces valeurs :

  • flex-start : les éléments sont placés au début
  • flex-end : les éléments sont placés à la fin
  • center : les éléments sont placés au centre
  • space-between : les éléments sont séparés avec de l'espace entre eux
  • space-around : idem, mais il y a aussi de l'espace au début et à la fin
  • stretch (par défaut) : les éléments s'étirent pour occuper tout l'espace

Voici ce que donnent les différentes valeurs :

order : changer de position

Sans changer le code HTML, nous pouvons modifier l'ordre des éléments en CSS grâce à la propriété order.

Indiquez simplement un nombre, et les éléments seront triés du plus petit au plus grand nombre.

Reprenons une simple ligne de 3 éléments :

#parent
{
    display: flex;
}

Si je dis que le premier élément sera placé en 3éme position, le second en 1ère position et le troisième en 2nde position, l'ordre à l'écran change !

.enfant:nth-child(1)
{
    order: 3;
}
.enfant:nth-child(2)
{
    order: 1;
}
.enfant:nth-child(3)
{
    order: 2;
}

Encore plus flex : faire grossir ou maigrir les éléments enfants

Allez encore une dernière technique, après on passe à la pratique.

Avec la propriété flex , nous pouvons permettre à un élément de grossir pour occuper tout l'espace restant.

.enfant:nth-child(2)
{
    flex: 1;
}

Le second élément s'étire pour prendre tout l'espace

Le nombre que vous indiquez à la propriété flex indique dans quelle mesure il peut grossir par rapport aux autres.

.enfant:nth-child(1)
{
    flex: 2;
}
.enfant:nth-child(2)
{
    flex: 1;
}

Ici, le premier élément peut grossir 2 fois plus que le second élément :

La propriété flex est une super-propriété qui combine flex-grow (capacité à grossir), flex-shrink (capacité à maigrir) et flex-basis (taille par défaut).

Dernière chose très importante, la valeur par défaut de flex est 0 1 auto;

Testez directement sur Codepen

Cliquez sur Edit on Codepen