Niveau Niveau confirmé

CSS3 Flexbox Layout module

Tutorielcss

Publié par le , mis à jour le (815063 lectures)

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”.

En février 2016 est sorti mon livre entièrement dédié à Flexbox. Il se nomme "CSS3 Flexbox : plongez dans les CSS modernes" et je vous recommande bien évidemment sa lecture afin de comprendre tous les rouages de ce positionnement révolutionnaire, et d'en maîtriser tous les aspects.

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

Data on support for the flexbox feature across the major browsers from caniuse.com

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

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 & @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.

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.

@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).

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.

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.

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

@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

@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 ?

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".

@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 ;)

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]".

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

Subtilité à préciser peut-être :
flex: 1;
équivaut en réalité à
flex-grow: 1; flex-shrink: 1, flex-basis: 0;
même si la valeur par défaut de flex-basis est en elle-même auto.
Et par ailleurs, il y a ces trois valeurs prédéfinies :
none => 0 0 auto.
auto => 1 1 auto.
initial => 0 1 auto.

Salut à tous,

mes tests de compatibilité de flexbox montrent qu'avant la 4.4.4 sur Android, l'affichage plante lamentablement.
Testant sur émulateur Android seulement (www.genymotion.com), j'arrive même à faire planter le navigateur natif quand Android est en 4.3.x ou antérieur.

Quelqu'un peut-il confirmer mon analyse ?

Commenter

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

Connectez-vous (déjà inscrit)

Oubli de mot de passe ? Pas de panique, on va le retrouver

Pas encore inscrit ? C'est très simple et gratuit.