Niveau : Confirmé

CSS3 Flexbox Layout module

Tutoriel par (Intégrateur du Dimanche, Strasbourg)
Créé le , mis à jour le (183815 lectures)
Tags : css, layout, flexible, flex, flexbox

Vous connaissez certainement le modèle de boîte classique en CSS et ses dispositions de type “block” ou “inline”, sachez que Flexbox CSS3 a été conçu pour étendre ce périmètre en introduisant un nouveau modèle de boîte distinct, que l’on appellera “le Modèle de boîte flexible”.

Au sein de ce schéma, on ne raisonne plus en “block” ou “inline”, ni même en float ou autres types de boîtes “classiques” CSS, mais en “Modèle de boîte flexible”, dont les quatre possibilités principales sont :

  1. Distribution des éléments horizontale ou verticale, avec passage à la ligne autorisé ou non,
  2. Alignements et centrages horizontaux et verticaux, justifiés, répartis,
  3. Réorganisation des éléments indépendamment de l’ordre du flux (DOM),
  4. Gestion des espaces disponibles (fluidité).

Note : ce tutoriel a été initialement rédigé en octobre 2010. Il a subi une refonte intégrale en décembre 2014 pour se mettre à jour.

En action !

Flexbox (le modèle de boîte flexible) se fonde schématiquement sur une architecture de ce type :

  • Un "flex-container" permettant de créer un contexte général d’affichage,
  • Un ou plusieurs "flex-item" qui ne sont rien d’autre que les enfants directs du conteneur, quels qu’ils soient.

Le "flex-container", qui définit le contexte global de modèle de boîte flexible, est tout simplement n’importe quel élément HTML doté de la déclaration display: flex; ou display: inline-flex;.
Ses enfants deviennent alors automatiquement (inutile de leur déclarer quoi que ce soit) des éléments de type "flex-item" :

.container {
	display: flex;
}

Un élément "flex-item" n’est plus considéré comme un “bloc” ou un “inline” classique (d’ailleurs les valeurs de display autre que none, et même certaines propriétés telles que float n’ont plus d’effet sur lui).

Démonstration display: flex

Compatibilité

N’ayons pas peur des mots : le module Flexbox est plutôt très bien reconnu par les navigateurs, même certains glorieux anciens et même sur les mobiles en général, comme en témoigne l’excellente ressource CaniUse.com.

Le seul retardataire est Internet Explorer qui ne supporte pas cette spécification pour ses anciennes versions (inférieures à IE10). Cela est éventuellement bloquant pour certains projets destinés à des ordinateurs de bureau.

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 Browser Android Browser 2.1+ - Ancienne spécification (2009). Avec préfixe -webkit-

Standardisation

L’état de l’art de la standardisation de “Flexible Box Layout Module” est pour le moins pittoresque tant il a connu de rebondissements.

Pour résumer, après trois refontes complètes depuis sa création en 2009, Flexbox était quasiment finalisé en 2012 (la spécification était au stade de “Candidate Recommandation”), puis, en septembre 2014 a été rétrogradé au stade de “Last Call Working Draft” (brouillon en dernier appel).

Pourquoi ce retour en arrière ?

Parce que les éditeurs de la spécification semblent vraiment souhaiter que ce module “ait de la gueule”, qu’il devienne une réelle solution à l’ensemble des contraintes actuelles de mise en forme CSS. Contraintes qui datent parfois de plus de 15 ans, comme le centrage vertical par exemple.

Est-ce grave ou bloquant ? Certainement pas, à condition de prendre quelques précautions sous la forme d’un outil génial qu’est Autoprefixer.

Distribution et axe principal

La distribution, c’est à dire le sens d’affichage horizontal ou vertical des éléments "flex-items" est définie par la propriété flex-direction dont les valeurs peuvent être :

  • row (distribution horizontale, valeur par défaut)
  • row-reverse (distribution horizontale inversée)
  • column (distribution verticale)
  • column-reverse (distribution verticale inversée)

Cette propriété s’applique au "flex-container" et détermine l’axe principal du modèle de boîte flexible.

.container {
	display: flex;
	flex-direction: column;
}

Démonstration flex-direction: column

flexbox 2

La propriété flex-wrap définit si le contenu sera distribué sur une seule ligne (ou colonne selon l’axe principal) ou sur plusieurs lignes. En clair, si les "flex-items" ont le droit de passer à la ligne ou non.

Les valeurs de flex-wrap sont :

  • nowrap (les éléments ne passent pas à la ligne, valeur par défaut)
  • wrap (les éléments passent à la ligne dans le sens de lecture)
  • wrap-reverse (les éléments passent à la ligne dans le sens inverse)
.container {
	display: flex;
	flex-wrap: wrap-reverse;
}

Démonstration flex-wrap: wrap-reverse

À noter qu’il existe une propriété raccourcie flex-flow qui regroupe flex-direction et flex-wrap .

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

Alignements

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

-L’alignement dans l’axe principal est traité via la propriété justify-content
- L’alignement dans l’axe secondaire est géré avec align-items

Ces deux propriétés s’appliquent au "flex-container".

Axe principal : justify-content

Les alignements dans l’axe de lecture principal sont définis à l’aide de la propriété justify-content, dont les valeurs possibles sont :

  • flex-start (éléments positionnés au début du sens de lecture, valeur par défaut)
  • flex-end (éléments positionnés à la fin)
  • center (position centrale)
  • space-between (répartition “justifiée”)
  • space-around (variante de répartition “justifiée”)
/* éléments positionnés en bas du conteneur */
.container {
	flex-direction: column;
	justify-content: flex-end;
}

Démonstration justify-content

flexbox 2b

Axe secondaire: align-items

Dans l’axe secondaire, les alignements sont régis via la propriété align-items, dont les valeurs sont :

  • flex-start (au début)
  • flex-end (à la fin)
  • center (au centre)
  • baseline (généralement identique à flex-start)
  • stretch (étirés dans l’espace disponible, valeur par défaut)
/* éléments étirés (valeur par défaut) */
.container {
	flex-direction: column;
	align-items: stretch;
} 

Démonstration align-items

align-items

Traiter les cas particuliers : align-self

La propriété align-self , permet de distinguer l’alignement d’un "flex-item" de ses frères. Les valeurs de cette propriété sont identiques à celles de align-items.

/* seul le paragraphe sera à droite */
.container {
	align-items: stretch;
}
p {
	align-self: flex-end;
}

Démonstration align-self

align-self

Propriété margin

La propriété margin lorsqu’elle est affectée à un "flex-item" ouvre de nouvelles perspectives, notamment dans l’axe vertical puisque Flexbox n’est plus lié à un sens de lecture en particulier.

En clair, il devient possible de positionner un élément en bas de son conteneur à l’aide d’un margin-top: auto, ou mieux : centrer à la fois horizontalement et verticalement via un simple margin: auto.

/* paragraphe centré horizontalement et verticalement */
.container {
	display: flex;
}
.container > p {
	margin: auto;
} 

Démonstration margin

Ordonnancement

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 propriété order s’applique aux "flex-items" et sa valeur initiale est 0.

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

Démonstration order

Flexibilité

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, qui s’appliquent aux "flex-items" et dont les fonctionnalités sont:

  • flex-grow : capacité pour un élément à s’étirer dans l’espace restant,
  • flex-shrink : capacité pour un élément à se contracter si nécessaire,
  • flex-basis : taille initiale de l’élément avant que l’espace restant ne soit distribué.

Par défaut, les valeurs de ces propriétés sont : flex-grow: 0, flex-shrink: 1 et flex-basis: auto.
En clair, les flex-items n’occupent initialement que la taille minimale de leur contenu.

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. L’espace disponible est alors tout simplement distribué entre les éléments flexibles.

Démonstration flex n°1

Gabarit flexible

flex 1

flex 2

Bonus : BFC

En guise de bonus, sachez que le modèle de boîte flexible dispose également de sérieux atouts lorsqu’il s’agit de dompter ces fichus flottants qui débordent tout le temps.

Les éléments "flex-container" et "flex-item" construisent un Block Formatting Context (BFC), ou plus exactement un Flex Formatting Context dont les avantages sont similaires et décrits dans cet article. :

  • un flottant ne déborde pas d’un "flex-container" ni d'un "flex-item",
  • un "flex-container" ou un "flex-item" ne s’écoule pas autour d’un flottant (ils demeurent à côté),
  • il n’y a pas de fusion de marges.

bfc

Conclusion

Flexbox est une spécification vaste et complexe, nous n’en n’avons démontré que les parties les plus utiles au quotidien 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 de nombreuses bonnes pratiques et attentes des webdesigners et intégrateurs depuis de longues années.

Dès aujourd’hui (ou dans un avenir proche selon votre cible), il constitue sans aucun doute la méthode de positionnement la plus pratique et polyvalente qui n’ait jamais existé en CSS.

Ressources

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

Articles et tutoriels connexes

jack in the flexbox

Commentaires

Olivier C a dit le

Ça peut être intéressant pour des adaptations sur mobile via les media queries, comme pour cette liste :
http://codepen.io/simurai/pen/dvklJ

jutoto a dit le

Ok, avec un outil comme LESS est il possible de paramétrer l'ensemble des règles intégrant tout les préfixe navigateur?
Je pense que oui, mais cela nous permet d’être rétrocompatible jusqu’où pour les principaux navigateur?

Est est ce que KNACSS intègre ces réglages (pré paramétrage des préfixes Flexbox)?
Merci

Raphael a dit le

@jutoto : "Est est ce que KNACSS intègre ces réglages (pré paramétrage des préfixes Flexbox)?" --> Oui :)

soykje a dit le

@Raphael & @jutoto : Pour avoir pas mal expérimenté Flexbox, il faut rester prudent sur l'intégration des différentes syntaxes via un préprocesseur (LESS) : certaines propriétés, valeurs, sont parfois très différentes (en particulier avec les quelques IE qui acceptent Flexbox...), et ne permettent ainsi pas toujours la factorisation. Néanmoins, l'essentiel des propriétés du module Flexbox se factorisent assez bien :)

Au passage, j'en profite pour rappeler qu'un bug a été signalé récemment, avec les dernières mises à jour de Firefox : https://bugzilla.mozilla.org/show_bug.cgi?id=1043520. La solution serait alors un *{min-height:0;min-width:0;}, que j'ai pu testé avec soulagement...

En bref, à mon sens, Flexbox est un outil puissant, mais il faut rester prudent. Baser un layout sur Flexbox peut être dangereux, tant les rendus des navigateurs, et le support, peuvent être changeants.

sacripant a dit le

Merci pour l'update de l'article. Je viens de passer plusieurs heures à expérimenter Flexbox, et j'ai l'impression d'être loin d'en avoir fait le tour.
Un point déjà qui m'échappe : en pratique, quelle différence entre flex-basis et width ? Dans mes différents essais, j'ai beau échanger ces 2 propriétés, j'obtiens toujours le même résultat.
Si quelqu'un pouvait me donner un cas où une valeur de width ne donnerait pas le même résultat que la même valeur avec flex-basis, ça m'aiderait certainement mieux à comprendre l'intérêt réel de cette nouvelle propriété et ce qu'elle a de spécifique.

kittyhello a dit le

Oh mais un grand OUI !
Merci Raphael pour le petit Jack.
Media queries au placard :)

Raphael a dit le

@soykje : "Baser un layout sur Flexbox peut être dangereux, tant les rendus des navigateurs, et le support, peuvent être changeants."
> À vrai dire ce n'est pas vraiment le boulot de Flexbox de créer des gabarits. Cette tâche est prévue pour un autre module CSS3 : "Grid Layout Module"... dont le support est malheureusement trop faible aujourd'hui.

@sacripant : de souvenir, sur un flex-item un flex-basis explicite prend toujours le pas sur la propriété width (mais demeure compatible avec min et max-width).

Sylleneor a dit le

Merci beaucoup pour ce tutoriel. Je pense qu'il va m'être très utile car j'essaye de rattraper mon retard sur le responsive web design.

parsimonhi a dit le

Très instructif. Je me demandais du coup s'il existait un moyen quelconque, lorsqu'on a un conteneur avec un display:flex; et un flex-flow:row wrap;, et à l'intérieur une liste d'un nombre indéterminé d’éléments, ayant tous la même taille, répartis sur plusieurs lignes, et occupant toute la largeur du conteneur (ayant donc un flex:1; si j'ai bien compris), de faire en sorte que les éléments de la dernière ligne aient la même largeur que les éléments des lignes du dessus au lieu de s'agrandir et d'occuper toute la largeur de cette dernière ligne?
J'ai fait un exemple en javascript pour aider à comprendre au cas où ça ne serait pas assez clair : http://jsfiddle.net/b92v5x1v/ (on peut faire ... la largeur de la fenêtre pour éventuellement avoir une meilleur idée de comment ça doit réagir). L'effet à obtenir me semble bien utile.

parsimonhi a dit le

@parsimonhi : je remets le lien qui a mal été interprété semble-t-il http://jsfiddle.net/b92v5x1v/

Raphael a dit le

@parsimonhi : non, malheureusement je ne crois pas. Mais j'aime bien ta bidouille JS ! ;)

jpdollo a dit le

Raphael
J'ai essayé le margin: auto et rien ne se passe
Merci de m'aider,j'ai du manquer quelque chose

Cordialement

LuciferX a dit le

Merci pour cet article fort instructif.

Pour ceux que ca intéresserait, voici un pense-bête sympa sur Flexbox: http://jonibologna.com/flexbox-cheatsheet/

Raphael a dit le

@jpdollo : La page de démo fonctionne chez toi ? Tu testes sur quel navigateur ? Tu as bien pensé aux préfixes, comme indiqué ?

BLVCK a dit le

@Raphael : Magnifique découverte concernant moi qui n’arrêtais pas de me poser des questions sur les nouveaux designs avec une multitude de boites je vais m'y mettre. Merci

sisyphe1980 a dit le

Bonjour,
j'ai bien suivi l'article mais j'ai une question la propriété flex s'applique sur le flex-container ou sur flex-item?

Oliboy50 a dit le

@Raphael : Merci pour ce super tutoriel. Néanmoins, il me semble qu'il y a une petite incohérence concernant l'utilisation de la propriété "flex" :

La propriété flex est un raccourci de trois propriétés, flex-grow, flex-shrink et flex-basis, qui s’appliquent au flex-container.

Cependant, tu utilises ces propriétés sur des "flex-items" juste après... une explication ?

adieng a dit le

Excellent tutoriel !!! Cependant, comme l'a souligné Oliboy50, une petite erreur s'est glissée sur l'utilisation de la propriété "flex". En fait "flex" s'applique à un "flex-item" au lieu du "flex-container".

Hermann a dit le

@Oliboy50 : Raphael a corrigé cette erreur que je lui ai signalée : la propriété flex s'applique aux flex-items et non pas au flex-container ;)

tackzak a dit le

Merci pour cet excellent tutoriel !
Sinon sur la partie "Propriété margin", la propriété que l'on doit définir est margin-bottom :
"...., il devient possible de positionner un élément en bas de son conteneur à l’aide d’un [margin-top: auto]".

semantic a dit le

Bonjour,
Le "Gabarit flexible" semble ne pas fonctionner correctement sur ie11 et ie 10.
La solution pour fixer le problème ajouter height :100vh à body

Bonne journée

Commenter

Vous devez être inscrit et identifié pour utiliser cette fonction.

Vous identifier (déjà inscrit)

Nouvel inscrit

Être inscrit sur Alsacréations vous permet de :

  • participer à la communauté
  • intervenir sur les actualités
  • créer des sujets sur le forum et y répondre
  • participer aux concours
  • vous inscrire à des événements tels que la KiwiParty
  • publier votre profil

Indiquez un e-mail valide pour recevoir votre mot de passe :

Votre adresse e-mail restera strictement confidentielle, ne sera ni divulguée à un tiers ni spammée.

Annonces par e-mail

Souhaitez-vous recevoir les newsletters officielles par e-mail ?   Fréquence d'envoi : tous les 3 à 6 mois, annulation possible à tout moment

En vous inscrivant, vous confirmez accepter les règles d'utilisation.

Retour à l'accueil