Flexbox (pour flexible box) est un mode de mise en page prévoyant une disposition des éléments d’une page de telle sorte que ces éléments possèdent un comportement prévisible lorsqu’ils doivent s’accommoder de différentes tailles d’écrans/appareils. Dans de nombreux cas, le modèle de boîte Flexbox offre une amélioration du modèle block dans lequel les flottements (float) ne sont pas utilisés, pas plus que la fusion des marges du conteneur flex avec ses éléments.
Beaucoup de designers trouveront le modèle de flexbox plus simple à utiliser. Les éléments enfants 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 les synthèses vocales et la navigation basées sur le code source.
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 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.
- Conteneur flex (Flex container)
- L’élément parent dans lequel chaque élément 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 boîte suit deux axes : L’axe principal (main axis) sur lequel les éléments flex se suivent. L’axe secondaire (cross axis) est 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 définit comment un seul élément flex est aligné sur l’axe secondaire et surcharge le comportement par défaut défini 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.
-
- Les propriétés min-height et min-width ont une valeur initiale de
auto
. - La propriété flex est un raccourci des propriétés flex-grow, flex-shrink et flex-basis pour établir la flexibilité des éléments flexibles.
- Les propriétés min-height et min-width ont une valeur initiale de
Déclarer une flexbox
Pour déclarer un élément utilisant ce style, définir la propriété display comme 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.
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 absolu et situés 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’alignement vertical des flexbox fait un « vrai » centrage contrairement aux autres méthodes d’alignement en CSS. Cela signifie que les éléments flex vont rester centrés, même s’ils débordent du conteneur 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’alignement sera étendue pour posséder une option "sécurisé" pour ce souci. 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-
, assignez 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ésents 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 ligne. A moins de pouvoir prédire à chaque fois quels éléments seront concernés sur chaque lignes, vous ne pouvez pas réellement utiliser le centrage basé sur les marges dans l’axe principal 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épendence 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 garde à l’ordre des éléments dans le code source pour ne pas gêner l’accessibilité du document.
Les propriétés des flexible box
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
etclear
n’ont pas d’effet sur un élément flex. Utiliserfloat
a pour effet d’attribuer la valeurblock
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="es"> <head> <style> .flex { /* style basique */ width: 350px; height: 200px; border: 1px solid #555; font: 1em 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 https://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>
Exemple 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.
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.
/* Layout */ * { box-sizing: border-box; /* pour maîtriser width et flex-basis */ } html { display: flex; flex-direction: column; /* correction bug IE de min-height non appliqué à body */ } body { display: flex; /* crée un contexte flex pour ses enfants */ flex-direction: column; /* affichage vertical */ min-height: 100vh; /* toute la hauteur du viewport */ padding: 1em; } .wrapper { flex: 1 1 auto; /* occupe la hauteur restante */ display: flex; /* crée un contexte flex pour ses enfants */ } nav, aside { width: 10em; } article { flex: 1; /* occupe la largeur restante */ } nav { order: -1; /* nav s'affiche en premier */ } /* Responsive (fenêtres de moins de 640px) */ @media (max-width: 640px) { .wrapper { flex-direction: column; /* affichage vertical */ } nav, aside { width: auto; /* pour écraser la valeur 10em */ } nav, aside, article { flex-basis: auto; /* pour écraser la valeur 0, due au flex: 1 */ } nav { order: 0; /* nav reprend sa place */ } } /* Decoration */ body { margin: 0; background: #999; font-family: arial, sans-serif; } header, nav, aside, article, footer { margin: .4em; padding: 1em; border-radius: 6px; } header { background: #ffeebb; } nav { background: #ccccff; } aside { background: #ccccff; } article { background: #dddd88; } footer { background: #ffeebb; }
<body> <header>header</header> <div class="wrapper"> <article>article</article> <nav>navigation</nav> <aside>aside</aside> </div> <!-- /wrapper --> <footer>footer</footer> </body>
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-after
, break-before
, et break-inside
ainsi que celles de CSS 2.1 page-break-before
, page-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] |
2.1-webkit [4] 4.4 |
11 |
12.1, 24 |
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.