<style> img { filter: hue-rotate(90deg); } </style> ## 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](https://codepen.io/alternative-rvb/pen/PoNrzYM)**, 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](https://i.imgur.com/U8DRwzH.png "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 ```html= <div id="parent"> <div class="enfant"></div> <div class="enfant"></div> <div class="enfant"></div> </div> ``` <!-- Mettre à jour --> CSS ```css #parent { display: flex; } ``` ![](https://i.imgur.com/vNK9AYO.png "Un coup de flex et les blocs se positionnent côte à côte !") ## 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). :::info 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. <!-- **`inline-flex`** : Cette valeur génère un container flex, de niveau inline, à l'intérieur de l'élément. --> ## 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 : ```css #parent { display: flex; flex-direction: column; } ``` ![](https://i.imgur.com/fXV0pnk.png "Les éléments sont disposés en colonne") :::warning 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 : ```css #parent { display: flex; flex-direction: column-reverse; } ``` ![](https://i.imgur.com/8mVlnho.png "Les éléments sont en colonne... dans l'ordre inverse !") 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 : ```css #parent { display: flex; flex-wrap: wrap; } ``` Voici l'effet que prennent les différentes valeurs sur une même illustration : ![](https://i.imgur.com/Gx3WDyT.png "Gestion du retour à la ligne avec flex-wrap") ## 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 : ```css #parent { display: flex; justify-content: space-around; } ``` ![](https://i.imgur.com/l1KoJy3.png "Les différentes valeurs possibles pour l'alignement avec justify-content") ```css #parent { display: flex; flex-direction: column; justify-content: center; height: 350px; /* hauteur pour que les éléments aient la place de bouger */ } ``` ![](https://i.imgur.com/oErjOZK.png "Avec une direction verticale (column), le centrage fonctionne de la même façon cette fois en hauteur !") ## 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](https://stackoverflow.com/questions/34606879/whats-the-difference-between-flex-start-and-baseline "Plus de détails sur Baseline") et [Article 2](https://www.prolificinteractive.com/2016/03/08/all-about-that-baseline-3/ "Plus de détails sur Baseline")) 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 !). ```css #parent { display: flex; justify-content: center; align-items: center; } ``` ![](https://i.imgur.com/YVfaL8f.png "Un alignement sur l'axe secondaire avec align-items nous permet de centrer complètement l'élément dans le conteneur !") Génial, voyez maintenant comme il simple de centrer verticalement et horizontalement. <!-- Dites que votre conteneur est une flexbox et établissez des marges automatiques sur les éléments à l'intérieur. C'est tout ! Essayez ! ```css #parent { display: flex; } .enfant { margin: auto; } ``` --> Il est possible de faire une exception pour un seul des éléments sur l'axe secondaire avec `align-self` : ```css #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 : ![](https://i.imgur.com/Z9INRV7.png "Un élément aligné différemment des autres avec align-self. Tiens je crois que j'ai dessiné une tête en pixel art !") ## 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 : ```css <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` : ```css #parent { display: flex; flex-wrap: wrap; } ``` ![](https://i.imgur.com/w7FfLOF.png "Plusieurs lignes dans une Flexbox") 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 : ![](https://i.imgur.com/d1ZjGJ2.png "Les lignes sont placées différemment avec align-content") ## 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 : ```css #parent { display: flex; } ``` ![](https://i.imgur.com/LLqZBpj.png "Une ligne de 3 éléments") 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 2^nde^ position, l'ordre à l'écran change ! ```css .enfant:nth-child(1) { order: 3; } .enfant:nth-child(2) { order: 1; } .enfant:nth-child(3) { order: 2; } ``` ![](https://i.imgur.com/zQbjw7H.png "Avec order, nous pouvons réordonner les éléments en CSS") ## 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. ```css .enfant:nth-child(2) { flex: 1; } ``` Le second élément s'étire pour prendre tout l'espace ![](https://i.imgur.com/FV3TTBu.png "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. ```css .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 : ![](https://i.imgur.com/BOLYa7U.png "Le premier élément peut grossir deux 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). :::warning 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** <iframe height="600" style="width: 100%;" scrolling="no" title="Flex with BEM notation Cheat Sheet" src="https://codepen.io/alternative-rvb/embed/PoNrzYM?height=265&theme-id=dark&default-tab=css,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href='https://codepen.io/alternative-rvb/pen/PoNrzYM'>Flex with BEM notation Cheat Sheet</a> by Alternative RVB (<a href='https://codepen.io/alternative-rvb'>@alternative-rvb</a>) on <a href='https://codepen.io'>CodePen</a>. </iframe> <!-- réf -->