CSS3 étend les possibilités de positionnement avec une nouvelle méthode : les boîtes flexibles (CSS Flexible Box Layout Module).
Dans la suite, les boîtes flexibles seront appelées simplement flexbox.

Par certains aspects, cette méthode de positionnement ressemble à un tableau qui n'aurait qu'une seule ligne de cellules car on a un élément conteneur avec des éléments items.
Par contre les possibilités d'agencement des items sont bien plus grandes que celles des cellules d'un tableau. En effet, les items d'une flexbox peuvent :

- se positionner dans 4 directions,
- être réordonnés et réarrangés,
- être agencés le long d'un axe principal ou d'un axe transversal (ie alignés horizontalement et verticalement),
- avoir leurs dimensions automatiquement mises à jour suivant la place disponible.

### Principes

#### Un conteneur, des items

éléments flexbox

Une structure de boîtes flexibles repose sur plusieurs éléments HTML.

Un élément joue le rôle de conteneur. Cet élément doit avoir sa propriété display avec la valeur `flex` ou `inline-flex`.

L'élément conteneur contient d'autres élements HTML, les items, qui vont se positionner à l'intérieur du conteneur suivant des propriétés CSS spécifiques aux flexbox.

Ce positionnement concerne les enfants du conteneur (ie 1er niveau d'imbrication), quelque soit le type d'élément de ces enfants. On peut donc avoir des enfants de même type (par exemple des p, des articles, des div, etc) ou de types différents et mélangés.

#### Direction d'affichage des items

La propriété flex-direction appliquée sur le conteneur définit dans quel sens vont s'afficher les items contenus. Les spécifications parlent de l'axe principal et de l'axe transversal, perpendiculaire à l'axe principal.

flex-direction: row
flex-direction: row-reverse
flex-direction: column
flex-direction: column-reverse

Tester la direction

L'exemple suivant montre un bandeau horizontal comme on pourrait en avoir dans la partie supérieure des pages d'un site.

Exemple : bandeau horizontal
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>Les CSS</title> <link href="styles.css" rel="stylesheet"> </head> <body> <nav> <div> Logo<br>du<br>site </div> <div> Menu 1 <ul> <li>Lien</li> <li>Lien</li> </ul> </div> <div> Menu 2 <ul> <li>Lien</li> <li>Lien</li> <li>Lien</li> </ul> </div> <div> Menu 3 <ul> <li>Lien</li> </ul> </div> </nav> </body> </html>
Fichier CSS : styles.css
/* le conteneur */ nav { display: flex; /* boîte flexible */ flex-direction: row; /* direction horizontale */ height: 140px; background: darkturquoise; } /* les items */ nav div { background: paleturquoise; margin: 10px; padding: 10px; } ul { margin: 0; }

L'exemple suivant montre un bandeau vertical.

Exemple : bandeau vertical
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>Les CSS</title> <link href="styles.css" rel="stylesheet"> </head> <body> <aside> <div> Publicité<br>numéro<br>1 </div> <div> La publicité<br>deux </div> <div> Pub<br>n°<br>3 </div> <div> Publicité 4 </div> </aside> </body> </html>
Fichier CSS : styles.css
/* le conteneur */ aside { display: flex; /* boîte flexible */ flex-direction: column; /* direction verticale */ width: 140px; height: 100%; /* la boîte prend toute la hauteur de la page */ background: darkturquoise; } /* les items */ aside div { background: paleturquoise; margin: 10px; padding: 10px; } /* forcer la hauteur de la page à la hauteur du navigateur */ html, body { margin: 0; height: 100%; }

### Alignements des items

#### Alignement sur l'axe principal

Une des caractéristiques très intéressante des boîtes flexibles tient dans l'alignement que l'on peut gèrer sur l'axe principal.
La propriété justify-content va non seulement permettre les alignements classiques (gauche / droite, haut / bas, centre) mais également des alignements qui tiennent compte des largeurs des items et calculent automatiquement l'espace entre eux.

justify-content avec axe principal horizontal
justify-content avec axe principal vertical

Tester direction et alignement sur l'axe principal

L'exemple suivant montre l'alignement des items dans un bandeau horizontal.

Exemple : bandeau horizontal
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>Les CSS</title> <link href="styles.css" rel="stylesheet"> </head> <body> <nav> <div> Logo<br>du<br>site </div> <div> Menu 1 <ul> <li>Lien</li> <li>Lien</li> </ul> </div> <div> Menu 2 <ul> <li>Lien</li> <li>Lien</li> <li>Lien</li> </ul> </div> <div> Menu 3 <ul> <li>Lien</li> </ul> </div> </nav> </body> </html>
Fichier CSS : styles.css
/* le conteneur */ nav { display: flex; /* boîte flexible */ flex-direction: row; /* direction horizontale */ justify-content: space-between; /* alignement principal */ height: 140px; background: darkturquoise; } /* les items */ nav div { background: paleturquoise; margin: 10px; padding: 10px; } ul { margin: 0; }

L'exemple suivant montre l'alignement des items dans un bandeau vertical.

Exemple : bandeau vertical
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>Les CSS</title> <link href="styles.css" rel="stylesheet"> </head> <body> <aside> <div> Publicité<br>numéro<br>1 </div> <div> La publicité<br>deux </div> <div> Pub<br>n°<br>3 </div> <div> Publicité 4 </div> </aside> </body> </html>
Fichier CSS : styles.css
/* le conteneur */ aside { display: flex; /* boîte flexible */ flex-direction: column; /* direction verticale */ justify-content: space-around; /* alignement principal */ width: 140px; height: 100%; /* la boîte prend toute la hauteur de la page */ background: darkturquoise; } /* les items */ aside div { background: paleturquoise; margin: 10px; padding: 10px; } /* forcer la hauteur de la page à la hauteur du navigateur */ html, body { margin: 0; height: 100%; }

#### Alignement sur l'axe transversal

Comme on peut le voir dans les exemples précédents, par défaut les items du conteneur occupent toute la largeur ou la hauteur de l'axe transversal.
La propriété align-items permet de gérer plus finement cet alignement.
La valeur `center` permet en particulier de centrer verticalement un élément par rapport à son conteneur de façon on ne peut plus simple.

align-items avec axe principal horizontal
align-items avec axe principal vertical

Tester direction et alignement sur l'axe transverval

L'exemple suivant montre l'alignement des items dans un bandeau horizontal.

Exemple : bandeau horizontal
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>Les CSS</title> <link href="styles.css" rel="stylesheet"> </head> <body> <nav> <div> Logo<br>du<br>site </div> <div> Menu 1 <ul> <li>Lien</li> <li>Lien</li> </ul> </div> <div> Menu 2 <ul> <li>Lien</li> <li>Lien</li> <li>Lien</li> </ul> </div> <div> Menu 3 <ul> <li>Lien</li> </ul> </div> </nav> </body> </html>
Fichier CSS : styles.css
/* le conteneur */ nav { display: flex; /* boîte flexible */ flex-direction: row; /* direction horizontale */ justify-content: space-between; /* alignement principal */ align-items: flex-start; /* alignemeent transversal */ height: 140px; background: darkturquoise; } /* les items */ nav div { background: paleturquoise; margin: 10px; padding: 10px; } ul { margin: 0; }

L'exemple suivant montre l'alignement des items dans un bandeau vertical.

Exemple : bandeau vertical
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>Les CSS</title> <link href="styles.css" rel="stylesheet"> </head> <body> <aside> <div> Publicité<br>numéro<br>1 </div> <div> La publicité<br>deux </div> <div> Pub<br>n°<br>3 </div> <div> Publicité 4 </div> </aside> </body> </html>
Fichier CSS : styles.css
/* le conteneur */ aside { display: flex; /* boîte flexible */ flex-direction: column; /* direction verticale */ justify-content: space-around; /* alignement principal */ align-items: center; /* alignement transversal */ width: 140px; height: 100%; /* la boîte prend toute la hauteur de la page */ background: darkturquoise; } /* les items */ aside div { background: paleturquoise; margin: 10px; padding: 10px; } /* forcer la hauteur de la page à la hauteur du navigateur */ html, body { margin: 0; height: 100%; }

#### Bandeau de navigation

A partir du code HTML ci-après, complétez le code CSS pour obtenir une page avec le bandeau de navigation ci-dessous.

bandeau de navigation

Toutes les images utilisées se trouvent dans le répertoire `../exemples/img`

La police utilisée est verdana, helvetica ou sans-serif avec une taille de 15 pixels.

L'image de fond de la page occupe automatiquement toute la surface de la page et se redimenssionne en même temps que la page. Elle s'appelle `metal_rivets.jpg`.

Le bandeau est fait avec une flexbox. Sa hauteur est de 140 pixels. Le fond est fait par un dégradé linéaire avec 3 points d'arrêt : `#ccc`, `#fcfcfc` et `#dcdcdc`. Il est entouré par une ombre sans décalage, avec un adouci de 2 pixels, un renfort de 4 pixels et de couleur `#322b25`.

L'image de gauche s'appelle `pirate.png` et mesure 115 pixels de large et 122 pixels de haut.

Les 3 boutons du centre sont des liens faits avec la balise a. La couleur de fond est est un gris léger (232 de rouge, vert et bleu) avec une transparence de 0.2. Le texte a pour couleur 41 de rouge, 34 de vert, 28 et de bleu. Le lien est entouré par une ombre sans décalage, avec un adouci de 3 pixels, un renfort de 1 pixel et de même couleur que le texte. Les images utilisées s'appellent respectivement `m1.png`, `m2.png` et `m3.png`. | dimensions des boutons centraux
Au survol de la souris, le texte des liens est ombré avec une ombre sans décalage, de 3 pixels d'adouci et de couleur 190 rouge, 190 vert et 190 bleu. Une ombre interne supplémentaire est également ajoutée au lien, sans décalage, avec un adouci de 5 pixels, un renfort de 2 pixels et de couleur 190 rouge, 190 vert et 190 bleu. | bouton survolé par la souris

dimensions des zones de saisie

Les 2 zones de saisie du formulaire ont les dimensions indiquées ci-contre.
Les 2 zones ont une bordure de 1 pixel de couleur `ACACAC`.
La couleur de fond est de couleur `F0F0F0`.
Quand les zones obtiennent le focus, le couleur de fond devient blanche.

dimensions de bouton de sousmission

Le bouton de soumission a les dimensions indiquées ci-contre.
Le fond du bouton est fait par un dégradé linéaire avec 3 points d'arrêt : `#ececec`, `#fcfcfc` et `#ccc`.
La couleur du texte est `#777`.
Quand la souris survole le bouton, la couleur du texte est faite avec 41 de rouge, 34 de vert et 28 de bleu. Le texte a une ombre sans décalage, avec un adouci de 3 pixels et de couleur 190 de rouge, de vert et de bleu. Le bouton a une ombre sans décalage, avec un adouci de 1 pixel et de couleur 41 de rouge, 34 de vert et 28 de bleu.

Code à compléter

Exercice : bandeau de navigation
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>Les CSS</title> <link href="styles.css" rel="stylesheet"> </head> <body> <header> <img> <nav> </nav> <form action="http://example.com/login.php"> </form> </header> </body> </html>
Fichier CSS : styles.css
CODE CSS A COMPLETER

Une solution possible

Exercice : bandeau de navigation
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>Les CSS</title> <link href="styles.css" rel="stylesheet"> </head> <body> <header> <img src="../exemples/img/pirate.png" id="logo"> <nav> <a href="#">Vaisseaux</a> <a href="#">Robots</a> <a href="#">Droïds</a> </nav> <form action="http://example.com/login.php"> <input type="text" name="txtPseudo" placeholder="Pseudo"> <input type="password" name="txtPasse" placeholder="Mot de passe"> <input type="submit" value="Entrage"> </form> </header> </body> </html>
Fichier CSS : styles.css
body { margin: 20px; background-image: url(../exemples/img/metal_rivets.jpg); background-position: center center; background-size: cover; background-attachment: fixed; /* raccourci background : background: url(../exemples/img/metal_rivets.jpg) center center / cover fixed; */ font: 15px verdana, helvetica, sans-serif; } header { display: flex; /* boîte flexible */ flex-direction: row; /* direction horizontale */ justify-content: space-between; /* alignement horizontal*/ align-items: center; /* alignement vertical */ height: 140px; padding: 0 10px; border-radius: 10px; background: linear-gradient(#ccc, #fcfcfc, #dcdcdc); box-shadow: 0 0 2px 4px #322b25; } nav { display: flex; /* boîte flexible */ flex-direction: row; /* direction horizontale */ justify-content: space-between; /* alignement horizontal*/ align-items: center; /* alignement vertical */ } /* liens du menu et formulaire */ nav a, header form { display: block; margin: 5px; width: 120px; min-width: 120px; height: 80px; border-radius: 5px; line-height: 140px; /* pour que les textes soient en bas de l'image de fond */ background-repeat: no-repeat; background-color: rgba(232, 232, 232, 0.2); color: rgb(41, 34, 28); box-shadow: 0 0 3px 1px rgb(41, 34, 28); text-align: center; text-decoration: none; } header form { height: 105px; } #logo { width: 115px; min-width: 115px; height: 122px; } /* images de fond des liens du menu */ nav a:nth-of-type(1) { background-image: url(../exemples/img/m1.png); } nav a:nth-of-type(2) { background-image: url(../exemples/img/m2.png); } nav a:nth-of-type(3) { background-image: url(../exemples/img/m3.png); } /* survol d'un lien du menu ou d'un bouton */ nav a:hover { box-shadow: 0 0 3px 1px rgb(41, 34, 28), 0 0 5px 2px rgb(190, 190, 190) inset; text-shadow: 0 0 3px rgb(190, 190, 190); } /* zones de saisie */ header input { display: block; width: 100px; margin: 10px auto; border: 1px solid #acacac; background: #f0f0f0; } /* changement couleur de fond quand zone activée */ header input:focus { background: white; } /* bouton du formulaire */ header input[type="submit"] { width: 80px; height: 2em; border-radius: 10px; background: linear-gradient(#ececec, #fcfcfc, #ccc); color: #777; cursor: pointer; } header input[type="submit"]:hover { color: rgb(41, 34, 28); box-shadow: 0 0 1px 0px rgb(41, 34, 28); text-shadow: 0 0 3px rgb(190, 190, 190); }