Utilisation des flexbox en CSS

par 2 contributeurs :

"La boîte flexible" (Flexible Box en anglais), ou flexbox (ce terme sera utilisé dans le reste de la page), issue du CSS3 est une mise en page qui fournit une disposition des éléments de la page de sorte que ceux-ci possèdent un comportement prévisible lorsque l'agencement de la page doit s'adapter en fonction des tailles d'écrans et des différents appareils. Utilisés dans de multiples cas, le modèle de flexible box offre une amélioration au modèle block dans lequel les flottements (float) ne sont pas utilisés, ni la fusion des marges du container flex et les marges de ses éléments.

Beaucoup de designers s'apercevront que le modèle de flexbox est plus simple à utiliser. Les éléments enfants/descendants d'une flexbox peuvent être placés dans n'importe quelle direction et peuvent avoir des dimensions pour s'adapter à la place disponible. Positionner les éléments enfants est ainsi plus simple et les agencements complexes peuvent être mis en place plus simplement et avec un code plus propre, étant donné que l'ordre d'affichage des éléments est indépendant de leur ordre dans le code source. Cette indépendance intentionnelle affecte seulement le rendu visuel, laissant l'ordre et la navigation basée sur l'ordre présents dans le code source.

Note : bien que la spécification CSS du modèles de Flexibles boxes soit  proche de l'état final (Last Call Working Draft stage, voir la dernière édition), certains navigateurs n'implémentent pas toutes les fonctionnalités des flexbox. Cependant, on trouve à présent un bon support sur les bases des flexbox. Vous pouvez retrouver dans le tableau de compatibilité chaque propriété avec sa prise en charge par les navigateurs à la date d'aujourd'hui.

Concept des flexible boxes

L'aspect principal d'une mise en page flex est la capacité à modifier la largeur et/ou la hauteur des éléments pour remplir au mieux l'espace disponible sur n'importe quel appareil. Un conteneur flex élargit les éléments pour remplir l'espace libre ou les rétrécir pour éviter les débordements.

L'algorithme d'agencement des flexbox est "direction-agnostic" (terme issu de la documentation anglaise), comme opposé à l'agencement en block, qui est verticalement biaisée, ou à l'agencement en ligne, qui est horizontalement biaisée. Tandis que l'agencement en block fonctionne bien pour les pages, sa définition n'est pas assez riche pour le support des applications dont les composants subissent des changements d'orientation, des redimensionnements, des agrandissements, ou des rétrécissements comme lorsque le user agent change, bascule verticalement vers horizontalement, et en avant. L'agencement via les flexbox est plus approprié pour des éléments d'une application et à petites échelles, alors que l'agencement en grille est destiné pour les agencements à large échelle. Les deux font partie d'un effort plus large du groupe de travaill CSS (the CSS Working Group) pour fournir une meilleure interopérabilité des applications web avec les différents user agents, les différents modes d'écritures et les autres demandes de flexibilités.

Vocabulaire des Flexible boxes

Bien qu'une première discussion sur les flexibles boxes ait permis de définir les termes comme horizontale/inline axe et vertical/block axe, il est nécessaire qu'une nouvelle terminologie décrive correctement le modèle. Reportez-vous au diagramme suivant lorsque vous lirez le vocabulaire des différents éléments listés ci-dessous. Il présente un conteneur flex qui possède une flex-direction à row, signifiant que tous les éléments flex vont se suivre horizontalement au travers de l'axe principal selon le sens de lecture établi, qui correspond à la direction des textes dans les éléments, dans ce cas, de gauche vers la droite.

flex_terms.png

Conteneur flex (Flex container)
L'élément parent dans lequel chaque éléments flex sera contenu. Un conteneur flex est défini lorsque la propriété display possède la valeur flex ou inline-flex.
Élément flex (Flex item)

Chaque enfant d'un conteneur flex devient un élément flex. Le texte directement contenu dans un conteneur flex est englobé dans un élément flex anonyme.

Axes

Toute flexible box suit deux axes. L'axe principal (main axis) est l'axe le long duquel les éléments flex vont suivre les autres. L'axe secondaire (cross axis) correspond à l'axe perpendiculaire à l'axe principal.

  • La propriété flex-direction établit l'axe principal.
  • La propriété justify-content définit comment les éléments flex sont positionnés le long de l'axe principal sur la ligne courante.
  • La propriété align-items définit comment les éléments flex sont positionnés le long de l'axe secondaire sur la ligne courante.
  • La propriété align-self  definit comment un seul élément flex est aligné sur l'axe secondaire et surcharge le comportement par défaut définit par align-items.
Directions
Le début/fin du côté principal et du côté secondaire du conteneur flex décrit l'origine et la fin du flux d'éléments flex. Ils suivent l'axe principal et secondaire du conteneur flex dans le sens établi par writing-mode (gauche-vers-droite, droite-vers-gauche, etc.).
  • La propriété order ordonne les éléments d'un groupe et détermine quel élément va apparaitre en premier.
  • La propriété flex-flow raccourcis les propriétés flex-direction et flex-wrap pour positionner les éléments flex.
Lignes (Lines)
Les éléments flex peuvent être positionnés soit sur une seule ligne, soit sur plusieurs lignes via la propriété flex-wrap, qui contrôle la direction de l'axe secondaire et la direction dans chaque nouvelle lignes rajoutées.
Dimensions
Les termes désignant la hauteur et la largeur des éléments flex sont la taille principale (main size) et la taille secondaire (cross size), qui suivent respectivement l'axe principal et l'axe secondaire du conteneur flex.

Désigner une flexible box

Pour désigner le CSS d'un élément utilisant ce style, fixer la propriété display comme ce qui suit :

display : flex

ou

display : inline-flex

Ainsi, cela définit l'élément comme un conteneur flex et ses enfants commes des éléments flex. La valeur flex transforme le contenu flex comme un élément de niveau block. La valeur inline-flex transforme le conteneur flex en un élément inline.

Note : les vendor prefix tag, s'ajoutent à la valeur de la propriété display et non pas sur l'attribut display lui-même. Par exemple, display : -webkit-flex.

Comportement des éléments flex

Le texte qui se trouve directement à l'intérieur d'un conteneur flex est automatiquement englobé dans un élément flex anonyme. Cependant, un élément flex anonyme qui contient uniquement un espace ne sera pas affiché, comme s'il possédait la propriété display:none.

La position statique des éléments placés en absolus et situé dans un conteneur flex est déterminée à partir du coin de départ de leur conteneur flex.

Actuellement, en raison d'un problème connu, spécifier visibility:collapse sur un élément flex aura pour conséquence de traiter l'élément comme s'il possédait display:none au lieu du comportement attendu, qui devrait être le même que s'il possédait visibility:hidden. La suggestion pour contourner le problème en attendant sa résolution est d'utiliser visibility:hidden pour les éléments flex qui doivent posséder le comportement de visibility:collapse. Pour plus d'information, voir bug 783470.

Les marges adjacentes des éléments flex ne sont pas collées. Utiliser les marges auto absorbera les espaces supplémentaire dans la direction verticale ou horizontale et peut être utilisée pour aligner ou séparer les éléments flex adjacents. Pour plus de détail, rendez-vous sur Aligning with 'auto' margins dans les specifications du W3C traitant du modèle de mise en page via les flexbox.

Pour assurer une taille minimum et raisonnable pour les éléments flex, utilisez min-width:auto et/ou min-height:auto. Pour les éléments flex, la valeur auto calcule la largeur/hauteur minimum de l'item pour ne pas être inférieur à la largeur/hauteur de son contenu, garantissant que l'élément sera affiché suffisament grand pour englober son contenu. Voir min-width et min-height pour plus de détails.

La propriété d'aligement des flexbox doit être "true" pour center contrairement aux autres méthodes de centrage en CSS. Cela signifie que les éléments flex vont rester centré, même s'ils débordent du contenur flex. Cela peut parfois être problématique, cependant, s'ils débordent au-delà du bord supérieur de la page, ou le bord gauche (dans les langages de la gauche vers droite comme en français; un problème survient sur le bord droit dans le cas des langages de la droite vers la gauche comme l'arabe), comme vous ne pouvez pas scroller vers cette zone, même si le contenu y est. Dans une sortie future, la propriété d'aligment sera étendue pour posséder une option "sécurisé" pour se soucis. Actuellement, si cela vous concerne, vous pouvez à la place exploiter les marges pour réaliser le centrage, comme ils le seront dans un cas "sécurisé" et arrêter le centrage si les élements dépassent. Au lieu d'utiliser les propriétés align-, assigner seulement les marges en auto sur les éléments flex que vous désirez center. Au lieu d'utiliser les propriétés justify-, assigner les marges en auto sur les bords extérieurs du premier et dernier éléments flex présent dans le conteneur flex. Les marges automatiques s'adapteront et vont prendre l'espace restant, centrant les éléments flex lorsqu'ils ont de l'espace supplémentaire, et en se placant dans un alignement normal si ce n'est pas le cas. Cependant, si vous essayez de remplacer justify-content par un alignement basé sur les marges dans le cas d'une flexbox contenant plusieurs lignes, vous n'aurez probablement pas de chance, puisque vous aurez besoin d'assigner les marges des premiers et derniers éléments de chaque lignes. A moins de pouvoir prédir à chaque fois quels éléments seront concerné sur chaque lignes, vous ne pouvez pas réellement utiliser le centrage basé sur les marges dans l'axe principale pour remplacer la propriété justify-content.

Rappelez-vous que l'ordre d'affichage des éléments est indépendant de leur ordre dans le code source, cette indépendant affecte uniquement le rendu visuel, laissant l'ordre de discours (speech order en anglais, je pense qu'il s'agit des lecteurs audio pour les personnes malvoyantes par exemple) et la navigation basés sur l'ordre du code source. Même la propriété order n'affectera pas l'ordre de discours de de navigation. De ce fait, les développeurs doivent prendre garder à l'ordre des éléments dans le code source pour ne pas gêner l'accessibilitée du document.

Les propriétés des flexible box

Flexible-boxes-related properties: margin, align-content, align-items, align-self, display, flex, flex-basis, flex-direction, flex-flow, flex-grow, flex-shrink, flex-wrap, justify-content, min-height, min-width, order

Les propriétés qui n'affectent pas les flexible boxes

Parce que les les flexibles boxes utilisent un algorithme différent d'affichage, plusieurs propriétés n'ont pas de sens sur un conteneur flex:

  • Les propriétés column-* des colonnes en CSS3 n'a pas d'effet sur un élément flex.
  • float et clear n'ont pas d'effet sur un élément flex. Utiliser float a pour effet d'attribuer la valeur block a la propriété display.
  • vertical-align n'a pas d'effet sur l'alignement des éléments flex.

Exemples

Exemple basique de flex

Cet exemple basique montre comment appliquer la "flexibilité" à un élent et comment les éléments enfants d'un même parent se comporte dans un état flexible.

​<!DOCTYPE html>
<html lang="en">
  <head>
    <style>

   .flex
   {
      /* style basique */
      width: 350px;
      height: 200px;
      border: 1px solid #555;
      font: 14px Arial;

      /* instaure la flexbox */
      display: -webkit-flex;
      -webkit-flex-direction: row;

      display: flex;
      flex-direction: row;
   }

   .flex > div
   {
      -webkit-flex: 1 1 auto;
      flex: 1 1 auto;

      width: 30px; /* Pour faire fonctionner correctement la transition. (Les transitions vers "width:auto" sont buggées dans Gecko et Webkit, au moins. Voir http://bugzil.la/731886 pour plus d'informations.) */

      -webkit-transition: width 0.7s ease-out;
      transition: width 0.7s ease-out;
   }

   /* colors */
   .flex > div:nth-child(1){ background : #009246; }
   .flex > div:nth-child(2){ background : #F1F2F1; }
   .flex > div:nth-child(3){ background : #CE2B37; }

   .flex > div:hover
   {
        width: 200px;
   }
   
   </style>
    
 </head>
 <body>
  <p>Flexbox nuovo</p>
  <div class="flex">
    <div>uno</div>
    <div>due</div>
    <div>tre</div>
  </div>
 </body>
</html>

Example d'un layout complet

Cet exemple démontre comment le système de flexbox offre la possibilité de changer dynamiquement l'affichage pour les différentes résolutions d'écrans. Le diagramme qui suit illustre la transformation.

HolyGrailLayout.png

Le cas illustré ici présente l'affichage d'une page adaptée à une fenêtre de navigateur qui doit être optimisée pour l'affichage sur un écran de smartphone. Ce n'est pas seulement les éléments qui sont réduis en taille, mais également l'ordre dans lequel ils sont affichés qui est sujet à changement. Flexbox permet de réaliser ceci facilement.

​
<!DOCTYPE html>
<html lang="en">
  <head>
    <style>

  body {
   font: 24px Helvetica;
   background: #999999;
  }

  #main {
   min-height: 800px;
   margin: 0px;
   padding: 0px;
   display: -webkit-flex;
   display:         flex;
   -webkit-flex-flow: row;
           flex-flow: row;
   }
 
  #main > article {
   margin: 4px;
   padding: 5px;
   border: 1px solid #cccc33;
   border-radius: 7pt;
   background: #dddd88;
   -webkit-flex: 3 1 60%;
           flex: 3 1 60%;
   -webkit-order: 2;
           order: 2;
   }
  
  #main > nav {
   margin: 4px;
   padding: 5px;
   border: 1px solid #8888bb;
   border-radius: 7pt;
   background: #ccccff;
   -webkit-flex: 1 6 20%;
           flex: 1 6 20%;
   -webkit-order: 1;
           order: 1;
   }
  
  #main > aside {
   margin: 4px;
   padding: 5px;
   border: 1px solid #8888bb;
   border-radius: 7pt;
   background: #ccccff;
   -webkit-flex: 1 6 20%;
           flex: 1 6 20%;
   -webkit-order: 3;
           order: 3;
   }
 
  header, footer {
   display: block;
   margin: 4px;
   padding: 5px;
   min-height: 100px;
   border: 1px solid #eebb55;
   border-radius: 7pt;
   background: #ffeebb;
   }
 
  /* Trop étroit pour supporter 3 colonnes */
  @media all and (max-width: 640px) {
  
   #main, #page {
    -webkit-flex-flow: column;
            flex-direction: column;
   }

   #main > article, #main > nav, #main > aside {
    /* Return them to document order */
    -webkit-order: 0;
            order: 0;
   }
  
   #main > nav, #main > aside, header, footer {
    min-height: 50px;
    max-height: 50px;
   }
  }

 </style>
  </head>
  <body>
 <header>header</header>
 <div id='main'>
    <article>article</article>
    <nav>nav</nav>
    <aside>aside</aside>
 </div>
 <footer>footer</footer>
  </body>
</html>

Expérimenter

Il existe plusieurs ressources en lignes pour expérimenter les flexbox:

Les choses a garder à l'esprit

L'algorithme décrivant comment les éléments flex sont disposés peut être parfois difficile. Voici quelques éléments à connaitre pour éviter les mauvaises surprises lorsque vous utiliser le système de flexible boxes.

Les flexibles boxes sont disposées en conformité avec le sens d'écriture, ce qui signifie que le point de départ et de fin des éléments s'accordent sur le début et la fin du texte.

Le début et la fin de l'axe secondaire se basent sur la valeur de la propriété direction.

Les sauts de pages sont possibles dans les affichages par flexible boxes via la propriété break-. Les propriétés CSS3 break-afterbreak-before, et break-inside ainsi que celles de CSS 2.1 page-break-beforepage-break-after, et page-break-inside sont acceptées sur un conteneur flex, un élément flex et à l'intérieur d'éléments flex.

Compatibilité des navigateurs

Feature Firefox (Gecko) Chrome Internet Explorer Opera Safari
Basic support (single-line flexbox) 18.0 (18.0)-moz(Behind a pref) [2]
22.0 (22.0) [2]
21.0-webkit
29.0
11 [3] 12.10, 17
15-16 -webkit
6.1-webkit [1]
Multi-line flexbox 28.0 (28.0) 21.0-webkit
29.0
11 [3] 12.10, 17
15-16 -webkit
6.1-webkit [1]
Feature Firefox Mobile (Gecko) Firefox OS Android IE Phone Opera Mobile Safari Mobile
Basic support (single-line flexbox) 18.0 (18.0)-moz(Behind a pref) [2]
22.0 (22.0) [2]

1.0-moz(Behind a pref) [2]
1.1

2.1-webkit [4]
4.4
11

12.1, 24
15-19 -webkit

7-webkit [1]
Multi-line flexbox 28.0 (28.0) 1.3 2.1-webkit [4]
4.4
11 12.1, 24
15-19 -webkit
7-webkit [1]

Voir également the Flexbugs project pour plus d'informations sur les bugs présents dans l'implémentations des flexbox.

Notes

[1] Safari jusqu'à 6.0 ( 6.1 pour iOS ) supporte une vieille version incompatible des spécifications. Safari 6.1 (7 pour iOS) a été mise à jour pour supporter la version finale.

[2] Passez à Firefox 22, pour activer le support des flexbox, l'utilisateur doit changer la configuration de "layout.css.flexbox.enabled" à "true" dans about:config. De Firefox 22 à Firefox 27, la configuration est à "true" par défaut, mais la configuration a été supprimée dans Firefox 28.

[3] Internet Exporer 10 supporte une vieille version incompatible des spécifications; Internet Explorer 11 a été mise à jour pour supporter la version finale.

[4] Le navigateur Android jusqu'à la version 4.3 supporte une vieille version incompatible des spécifications. Android 4.4 a été mise à jour pour supporter la version finale.

Étiquettes et contributeurs liés au document

Étiquettes : 
Contributeurs à cette page : ChristopheBoucaut, Goofy
Dernière mise à jour par : ChristopheBoucaut,