CSS3 Flexbox Layout module

Openweb.eu.org > Articles  > CSS3 Flexbox Layout module

Abstract

Parmi les nouveaux modules apportés par CSS3 se trouve « CSS Flexible Box Layout », qui peut être traduit par « modèle de boîte flexible ».

Raphaël Goetter nous explique les principes et les possibilités de ce module qui risque fortement de révolutionner nos pratiques en termes de positionnement CSS.

Article

Positionner correctement des éléments en CSS s'est toujours révélé être une mission aussi palpitante que fastidieuse en raison d'un lourd passé de navigateurs assez peu enclins à suivre des standards communs.

Depuis sa création, CSS propose officiellement quatre types de rendus d'éléments :

  • Le rendu «bloc»
  • Le rendu «inline»
  • Le rendu «tabulaire»
  • Le rendu «positionné»

Chacune des valeurs de la propriété display (par exemple inline-block), de float, ou de position, renvoie à l'un de ces quatre types de rendus.

CSS3 étend ce périmètre en introduisant un nouveau modèle de boîte «flexible» : flexbox, ou Flexible Box Layout Module.

Flexbox est un nouveau mode de positionnement, introduit via la propriété display, permettant de créer un contexte général d'affichage sur un parent et d'en faire hériter ses enfants :

  • Distribution en bloc ou en ligne,
  • Alignements horizontaux et verticaux,
  • Gestion des espaces disponibles (fluidité à l'instar des cellules de tableau),
  • Réorganisation des éléments indépendamment de l'ordre du flux (DOM).

Compatibilité de Flexbox module

Commençons par calmer les plus optimistes d'entre vous et ceux que je vois déjà en train de se ruer sur leur éditeur HTML préféré.

Posons d'entrée le décor ; j'ai deux bonnes nouvelles et une mauvaise :

  • La première bonne nouvelle est que les spécifications concernant Flexbox sont au stade de «Candidate Recommandation» et peuvent être aujourd'hui considérées comme stables.
  • La seconde bonne nouvelle est que l'implémentation de Flexbox sur les navigateurs est «relativement correcte», comme en témoigne l'excellente ressource Caniuse.
  • La mauvaise nouvelle est que les spécifications ont radicalement changé plusieurs fois et que les navigateurs compatibles sont susceptibles de reconnaître l'une ou l'autre des versions des spécifications, parfois de manière incomplète, et - bien entendu - avec moult préfixes de partout !

Malgré ces quelques petites embûches, consolez-vous en vous rappelant notamment que dans le monde du Web mobile, les navigateurs récents sont déjà parfaitement prêts à afficher vos sites web dans ce mode de positionnement avant-gardiste.

Tableau des compatibilités

Navigateurs Versions Détails
Internet Explorer Internet Explorer 10+ IE mobile 10+ - Ancienne spécification pour IE10 (2011). Avec préfixe -ms-
- Spécification finale sans préfixe pour IE11
Firefox Firefox 2+ - Ancienne spécification (2009). Avec préfixe -moz-
- Spécification finale sans préfixe depuis Firefox 22
Chrome Chrome 4+ Chrome Mobile (Android 4) - Ancienne spécification (2009) depuis Chrome 4. Avec préfixe -webkit-
- Spécification finale depuis Chrome 21. Avec préfixe -webkit-
- Spécification finale sans préfixe depuis Chrome 29.
- Ancienne spécification pour Chrome sur Android. Avec préfixe -webkit-
Opera Opera 12.1+ Opera Mobile 12.1+ - Spécification finale sans préfixe entre les versions 12 et 15.
- Spécification finale depuis Opera 16. Avec préfixe -webkit-
Safari Safari 3.1+ Safari Mobile (iOS 3.2+) - Ancienne spécification (2009). Avec préfixe -webkit-.
- Spécification finale depuis Safari 7. Avec préfixe -webkit-
Android Android Browser 2.1+ Ancienne spécification. Avec préfixe -webkit-

Des spécifications fluctuantes

Comme vous l'avez judicieusement constaté à la lecture attentive du tableau de compatibilité, la spécification de Flexbox a connu différentes étapes de syntaxe et nommage.

Pour tout vous avouer, il y a eu trois syntaxes très différentes au cours de l'évolution de ce module :

Syntaxe 2009 Syntaxe 2011 Syntaxe 2012 (finale)
display : box display : flexbox display : flex
box-flex flex flex
box-ordinal-group flex-order order
box-orient flex-direction flex-direction
box-pack + box-align flex-pack justify-content + align-items

Pour des raisons pratiques évidentes, nous nous contenterons des syntaxes standardisées et sans préfixes au sein de cet article, il vous incombera de rajouter tous les préfixes constructeurs si vous désirez appliquer les exemples de codes sur votre navigateur préféré.

Appliquer Flexbox

Le principe général de Flexbox peut paraître assez déroutant de prime abord, mais finalement très pratique : il suffit de créer un «contexte de boîte flexible» sur un parent à l'aide de la propriété display afin qu'il soit appliqué à l'ensemble de ses enfants directs.

Tout au long de cet article et pour l'ensemble des exemples pratiques, nous avons choisi le navigateur Google Chrome, actuellement le plus à même de supporter cette spécification dans sa dernière version stable. Cependant, rien ne devrait vous empêcher de tester sur d'autres navigateurs.

En clair, la règle suivante va affecter les éléments enfants de .kiwi :

.kiwi {display: flex;}

flex01

Démonstration display: flex

Modifier l'orientation

L'un des premiers avantages de ce type de positionnement est de pouvoir jongler aisément entre une disposition d'éléments sous forme de colonnes (blocs) ou de lignes (inlines).

Pour ce faire, il suffit là encore d'indiquer ce comportement sur le parent à l'aide de la propriété flex-direction :

/* les enfants s'affichent en colonne */
.kiwi {flex-direction: column;} 

/* les enfants s'affichent en ligne */
.kiwi {flex-direction: row;} 

flex02

Démonstration flex-direction: column

Le suffixe -reverse inverse l'ordre d'affichage :

/* les enfants s'affichent en colonne inversée */
.kiwi {flex-direction: column-reverse;} 

/* les enfants s'affichent en ligne inversée */
.kiwi {flex-direction: row-reverse;} 

flex02b

Démonstration flex-direction: column-reverse

Dans la lignée de flex-direction, signalons l'existence de la propriété intéressante flex-wrap.

Cette propriété autorise (ou non) les éléments à s'afficher sur plusieurs lignes lorsqu'elles dépassent de leur conteneur, les valeurs étant les suivantes :

  • flex-wrap: nowrap : les éléments demeurent toujours sur une ligne, et peuvent déborder
  • flex-wrap: wrap : les éléments passent à la ligne plutôt que de déborder
  • flex-wrap: wrap-reverse : les éléments passent à la ligne… en inversant leur direction

flex03

Démonstration flex-wrap: wrap

flex03b

Démonstration flex-wrap: wrap-reverse

Pour votre culture personnelle, sachez qu'il existe une propriété raccourcie flex-flow qui regroupe flex-direction et flex-wrap.
Ne vous étonnez donc pas de rencontrer parfois la syntaxe .kiwi {flex-flow: column;}

/* affichage en ligne et passage à la ligne autorisé */
.kiwi {flex-flow: row wrap;} 

Gérer les alignements horizontaux et verticaux

Flexbox propose de gérer très finement les alignements et centrages, en différenciant les deux axes d'affichage de cette manière :

  • Les alignements dans l'axe principal sont traités via la propriété justify-content et ses différentes valeurs : flex-start, flex-end, center, space-between et space-around
  • Les alignements dans l'axe secondaire sont gérés avec align-items et ses valeurs : flex-start, flex-end, center, baseline, stretch

Exemple de centrage horizontal et vertical :

.kiwi {
	justify-content: center;
	align-items: center;
} 

flex04

Démonstration justify-content

flex05

Démonstration align-items

Alignement : gérer les exceptions

La propriété align-self offre la possibilité de se distinguer un élément particulier de ses frères en adoptant un alignement différent.

Attention toutefois, cette méthode peut dans certains cas causer des soucis d'accessibilité lorsque la feuille de style est désactivée (Cf Accessiweb 2.2 critère 10.3).

.kiwi > li:last-child {
	align-self: flex-end;
} 

flex05b

Démonstration align-self

Autre astuce, la propriété margin et sa valeur auto permettent de positionner un élément en dehors de la distribution de ses frères.

Il devient donc possible d'afficher un groupe d'élément à gauche du parent et d'en placer un à droite :

.kiwi {
	justify-content: flex-start;
} 
.kiwi > li:last-child {
	margin-left: auto;
}

flex05c

Démonstration margin: auto

Jouer avec la flexibilité des éléments

Cela ne devrait étonner personne, la notion de flexibilité constitue le fondement du module de positionnement Flexbox, et c'est là qu'intervient l'indispensable propriété flex.

La propriété flex est un raccourci de trois propriétés, flex-grow, flex-shrink et flex-basis, dont les fonctions sont :

  • flex-grow : propension pour un élément à s'étirer dans l'espace restant
  • flex-shrink : propension pour un élément à se contracter si besoin
  • flex-basis : taille initiale de l'élément avant que l'espace restant ne soit distribué

Les particularités des propriétés de flexibilité étant assez nombreuses (et leurs spécifications assez alambiquées), je vous propose un petit résumé explicatif simplifié :

Pour rendre un élément flexible, il suffit de lui attribuer une valeur de flex-grow (ou flex en raccourci) supérieure à zéro.
Cet élément occupera alors l'espace restant au sein de son conteneur :

/* .salade occupera l'espace restant */
.salade {
  flex: 1;
}

Plusieurs éléments peuvent être rendus flexibles et se répartir l'espace restant.

Dans l’exemple ci-dessous, l’espace total est découpé en 4 (1+2+1), puis partagé entre les trois éléments selon le «poids» attribué à chacun. En l’occurrence, le troisième occupera la moitié de l’espace (2/4), les deux autres se partageant le reste par parts égales.

.salade {
  flex: 1;
}   
.tomate {
  flex: 2;
}   
.oignons {
  flex: 1;
}

En ajoutant une valeur supplémentaire, celle de flex-basis, il est possible d'indiquer une largeur minimale préférée qui sera appliquée tant qu'il n'y a pas d'espace superflu :

.salade {
  flex: 1 200px;
}   
.tomate {
  flex: 2 400px;
}   
.oignons {
  flex: 1 200px;
}

flex06

Démonstration flex n°1

flex06b

Démonstration flex n°2

Gabarit flexible

Réordonner les éléments au sein de leur parent

L'une des fonctionnalités les plus avant-gardistes du modèle d'affichage Flexbox est de pouvoir réordonner à sa guise chacun des éléments indépendamment grâce à la propriété order.

Les valeurs de order agissent telles des pondérations : les éléments dont la valeur est la plus forte se trouveront en bas de la pile. La valeur initiale de order est 0.

/* le premier de la liste s'affichera en bas de pile */
li:first-child {
	order: 1;
}

flex07

Démonstration order

Démonstration navigation

Pour aller plus loin

Voici quelques ressources externes pour en savoir plus sur ce positionnement très polyvalent :

Articles et tutoriels connexes :

Alternatives :

Il existe un outil de type «polyfill» afin d'émuler le support de Flexbox sur les anciens navigateurs tels IE6-IE9 et Opera 10. Il s'agit de Flexie.js. Vous pouvez le tester sur Flexie Playground. Sachez cependant que cette alternative JavaScript ne semble plus mise à jour depuis une bonne année et se base sur la syntaxe désuette de 2009.

Conclusion

Flexbox est une spécification vaste et complexe, nous n'en n'avons exploré que les parties les plus exploitables mais d'autres recoins restent à explorer et seront dévoilés au fur et à mesure de leur support avec les navigateurs.

Quoi qu'il en soit, le positionnement Flexible Layout regroupe beaucoup de bonnes pratiques et attentes des webdesigners et intégrateurs depuis de longues années. Dans un avenir proche (ou dès maintenant selon votre cible), il constitue sans aucun doute la méthode de positionnement la plus pratique et polyvalente.

Remarque finale : cet article est publié conjointement sur les sites web OpenWeb et Alsacréations.

À propos de cet article

  • Openweb.eu.org
  • Profil : Expert, Gourou
  • Technologie : CSS
  • Thème : Mise en page
  • Auteur :
  • Publié le :
  • Mise à jour : 27 septembre 2013
  • 6 commentaires

Vos commentaires

  • lapouth Le 25 novembre 2012 à 07:40

    Cet article, avec ses liens externes, a permis l’évolution de mon site que voilà http://laridictionnaire.perso.sfr.fr/.
    Toutefois, sur opera, les boites ont un ordre différent. C’est le seul qui fait ça ! (?)
    Merci pour ce que vous faites, et à bientôt(chez vous !)
    Nsàyì ! Que la joie soit avec vous !

  • Raphael Le 25 novembre 2012 à 09:53

    Bonjour Lapouth,

    En fait c’est tout à fait normal : vous avez employé la syntaxe de Flexbox sans aucun préfixe. Du coup, seul Opera (et IE10) interprêtent ce module.
    Pour tous les autres navigateurs, il faut ajouter des préfixes constructeurs comme cela est expliqué au sein de l’article.

    Bonne continuation,

    Raphaël

  • Deumus Le 15 décembre 2012 à 00:53

    Est-ce moi ou l’intérêt principal de ce module sera surtout tourné vers les menus ou pour un design "metro" ?
    J’ai une imagination presque nulle en matière de design web, je me trompe peut-être...

  • lapouth Le 20 décembre 2012 à 21:36

    Raphaël bonjour,
    Grâce à ce que vous m’avez dit, d’une relecture attentive de votre article, et de ses annexes, m’ont permis de corriger le bug.
    Merci ! Nsàyí Que la joie soit avec vous !
    Lapouth.

  • Raphael Le 23 décembre 2012 à 21:15

    Deumus : il y a de très nombreux intérêts à ce module : il regroupe presque tous les avantages de tous les autres types de positionnement (tableaux, position, float, etc.) sans en avoir les inconvénients :
     centrages verticaux et horizontaux sans bidouilles
     réordonnement d’éléments sans bidouilles
     décalages, hauteurs automatiques, etc.

    Un exemple simple : déplacer un bloc de navigation en bas de page sur petit écran (pour ne pas parasiter la lecture) : http://lab.goetter.fr/post/37802971764/deplacer-des-elements-selon-la-taille-decran-version

  • Clochix Le 23 décembre 2012 à 21:36

    Merci pour la présentation :)

    Pour info sur la disponibilité : l’implémentation de la version finale de flexbox est arrivée, sans préfixe, dans Firefox Nightly en décembre 2012, et devrait être dans Firefox 20 ou 21 (donc en avril ou mai 2013) ( cf http://blog.dholbert.org/2012/12/css3-flexbox-enabled-in-nightlies-ready.html ) ;

    Webkit attendait que quelqu’un d’autre se lance pour dé-préfixer à son tour donc ça ne saurait tarder : https://bugs.webkit.org/show_bug.cgi?id=98420

Vos commentaires

modération a priori

Attention, votre message n’apparaîtra qu’après avoir été relu et approuvé.

Qui êtes-vous ?
Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Suivre les commentaires : RSS 2.0 | Atom