Dernière mise à jour le 13 novembre 2022
La stratégie de mise en page présentée ici, les grilles CSS (CSS grids), est la plus récente de toutes.
Elle est aussi très intuitive au niveau conception.
On commence par créer une grille virtuelle, puis on y place les éléments, ceux-ci pouvant recouvrir plusieurs cellules.
header | header | header |
aside | section | section |
aside | section | section |
footer | footer | footer |
L'ordre de déclaration des éléments sémantiques (éléments structurants) n'a même plus d'importance!
Et surtout, on peut décider comment la page sera réorganisée lorsque change la taille de l'écran :
header | header |
footer | footer |
section | section |
section | section |
aside | aside |
Voyons un exemple...
Supposons que nous voulions une mise en page basée sur une grille de 3 x 3 (9 cellules), avec une colonne centrale qui a deux fois la taille des autres.
1 | 2 | 2 |
4 | 5 | 6 |
7 | 8 | 9 |
Dans un but de simplicité nous n'utiliserons pas d'éléments sémantiques, mais seulement des div.
Il s'agit d'abord de déclarer nos 9 div et de les regrouper dans un conteneur (lui aussi un div).
C'est ce conteneur qui implémentera la grille avec display:grid.
#conteneur { display: grid; ... } <div id="conteneur"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> <div>7</div> <div>8</div> <div>9</div> </div>
Il faut ensuite spécifier le nombre de colonnes et pour cela il y a plusieurs façons.
On peut déclarer le nombre de colonnes en indiquant du même coup la taille à l'aide des unités CSS (généralement le pourcentage) :
#conteneur { display: grid grid-template-columns: 25% 50% 25%; ... }
On peut aussi utiliser les fractions :
#conteneur { display: grid grid-template-columns: 1fr 2fr 1fr; ... }
Enfin, si toutes les colonnes ont la même largeur, on peut utiliser la fonction repeat :
#conteneur { display: grid /* grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; */ grid-template-columns: repeat(6, 1fr); ... }
Dans l'exemple suivant, la largeur de la mise en page a été réduite à 480px pour faciliter l'affichage dans ce document.
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title>Les grilles CSS</title> <style> body { text-align: center; } #conteneur { display: grid; grid-template-columns: repeat(3, 1fr); max-width: 480px; margin: 0 auto; } #conteneur div { background: yellow; padding: 20px; } #conteneur div:nth-child(even) { background: lime; } </style> </head> <body> <div id="conteneur"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> <div>7</div> <div>8</div> <div>9</div> </div> </body> </html>
Par défaut, la hauteur des rangées s'ajuste au contenu (en plus de la valeur de la propriété padding).
On peut aussi fixer la hauteur des rangées.
Voici l'exemple d'une grille de 6 colonnes et de 3 rangées (les deux premières d'une hauteur de 100px, la trosième de 50px) :
#conteneur { display: grid grid-template-columns: repeat(6, 1fr); grid-template-rows: 100px 100px 50px; ... }
Ici les rangées auront toutes la même hauteur, peu importe leur nombre :
#conteneur { display: grid grid-template-columns: repeat(6, 1fr); grid-auto-rows: 100px; ... }
On peut aussi s'assurer d'une hauteur minimale, tout en permettant l'étirement vertical si le contenu l'exige :
#conteneur { display: grid grid-template-columns: repeat(6, 1fr); grid-auto-rows: minmax(100px, auto); ... }
Dans l'exemple suivant, on utilise la fonction repeat pour donner les mêmes valeurs de minimum et de maximum aux trois rangées :
#conteneur { display: grid grid-template-columns: repeat(6, 1fr); grid-template-rows: repeat(3, minmax(100px, auto)); ... }
Avant de voir un exemple complet, signalons qu'il est aussi possible de spécifier l'espace entre les les colonnes et entre les rangées :
#conteneur { display: grid grid-template-columns: repeat(6, 1fr); grid-template-rows: repeat(3, minmax(100px, auto)); column-gap: 20px; row-gap: 20px; ... }
Ces deux dernière propriétés pourraient être remplacées par une seule : grid-gap: 20px;.
Et maintenant un exemple complet pour pratiquer...
body { text-align: center; } #conteneur { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: minmax(100px, 150px); /* la ligne suivante afficherait tout */ /* grid-auto-rows: minmax(100px auto); */ column-gap: 20px; row-gap: 10px; max-width: 480px; margin: 0 auto; } #conteneur div { background: yellow; padding: 20px; } #conteneur div:nth-child(even) { background: lime; }
Nous avons vu qu'à l'intérieur d'un conteneur ayant la propriété display:grid, les éléments sont placés dans la grille virtuelle selon l'ordre de leur déclaration dans le fichier HTML.
Mais il s'agit là du comportement par défaut.
Il existe une façon beaucoup plus souple de positionner les éléments, soit en utilisant les lignes de colonnes et les lignes de rangées.
Ces lignes, que l'on peut voir dans la figure suivante, débute à 1 et vont jusqu'à n+1 où n est le nombre de colonnes ou le nombre de rangées.
Voyons un exemple...
Supposons une grille de 6 x 4 contenant 6 éléments (pour l'instant encore des div).
Au départ, les éléments sont positionnés chacun dans une cellule selon l'ordre de déclaration :
Maintenant, supposons que l'objectif final est de les postionner ainsi :
On remarque que la sixième élément (gris) est passé devant le cinquième (noir).
Commençons par définir le nombre de colonnes et de lignes de la grille :
#conteneur { display: grid; grid-template-columns: repeat(6, 1fr); /* 6 colonnes */ grid-template-rows: repeat(4, minmax(75px, auto)); /* 4 rangées */ grid-gap: 10px; max-width: 480px; margin: 0 auto; } .un { background-color: red; } .deux { background-color: green; } ... <div id="conteneur"> <div class="un"></div> <div class="deux"></div> ...
Maintenant, commençons à positionner les éléments en spécifiant les lignes de départ et de fin :
.un { background-color: red; grid-column-start: 1; grid-column-end: 3; }
On peut aussi utiliser une notation abrégée :
.un { background-color: red; grid-column: 1/3; } .deux { background-color: green; grid-column: 3/7; }
Notons qu'il n'est pas nécessaire de spécifier ici les lignes de rangées, puisque les éléments n'occupent en hauteur qu'une seule rangée.
Poursuivons en plaçant le troisième item sur trois colonnes et deux rangées :
.trois { background-color: blue; grid-column: 1/4; /* grid-row-start: 2; */ /* grid-row-end: 4; */ grid-row: 2/4; }
Et plaçons le reste des éléments...
.quatre { background-color: yellow; grid-column: 4/7; grid-row: 2/4; } /* cinq positionné après six */ .cinq { background-color: black; grid-column: 3/7; } .six { background-color: gray; grid-column: 1/3; grid-row: 4; }
C'est cependant avec le concept de zones que les grilles CSS montrent toute leur souplesse et toute leur puissance.
Supposons par exemple que nous voulions réaliser la mise en page suivante :
Cette fois nous allons utiliser les éléments sémantiques appropriés et non plus des conteneurs généraux comme l'élément div.
Sans spécifier le nombre de colonnes et de rangées, ni la position exacte des éléments, ces derniers s'empilent simplement à la verticale.
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title>Les grilles CSS</title> <style> body { text-align: center; } #conteneur { display: grid; grid-gap: 10px; max-width: 480px; margin: 0 auto; } #conteneur > * { background-color: lime; padding: 30px; } </style> </head> <body> <div id="conteneur"> <header>header</header> <main>main</main> <section>section</section> <aside>aside</aside> <nav>nav</nav> <footer>footer</footer> </div> </body> </html>
Utilisons maintenant la propriété grid-area pour assigner à chaque élément une position dans la grille.
Cette position est exprimée sous la forme d'une chaîne de caractères.
header { grid-area: header; } main { grid-area: main; } section { grid-area: section; } aside { grid-area: aside; } nav { grid-area: nav; } footer { grid-area: footer; }
Dans notre exemple, le nom de la zone dans laquelle sera positionné l'élément (la valeur de la propriété grid-area) correspond au nom de l'élément.
Par exemple, nous avons choisi de nommer "header" la zone où sera postionné l'élément header.
Il s'agit d'une pratique répandue, mais pas du tout obligatoire.
Le code suivant serait tout aussi valable :
header { grid-area: entete; }
Déclarons maintenant le nombre de colonnes et de rangées :
#conteneur { display: grid; grid-template-columns: repeat(4, 1fr); /* 4 colonnes */ grid-auto-rows: minmax(75px, auto); /* autant de rangées qu'il faut */ grid-gap: 10px; max-width: 480px; margin: 0 auto; ...
Puis, plaçons dans la grille les zones correspondant aux éléments structurants :
#conteneur { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: minmax(75, auto); grid-gap: 10px; max-width: 480px; margin: 0 auto; grid-template-areas: "header header header header" "aside aside main main" "nav nav main main" "section section section section" "footer footer footer footer"; /* ne pas oublier le point-virgule */ }
Et voilà!
Changer la position ou la superficie occupée par un élément se résume maintenant à "jouer" avec les zones du grid-template-area.
Pour vous convaincre d'utiliser les mises en page à l'aide de grilles CSS, il reste à vous montrer comment il est facile de les adapter à différentes tailles d'écran.
C'est ce qu'on appelle le design adaptatif (responsive design).
Dans l'exemple de la section précédente, la mise en page visait de toute évidence un écran d'ordinateur.
Voyons maintenant comment il est possible d'adapter rapidement cette mise en page à un écran de taille inférieure, comme celui d'un téléphone cellulaire.
Pour cela nous allons utiliser la règle @media
Les énoncés CSS qui débutent par le symbole "@" sont appelées en anglais at-rules (le a commercial se disant at sign en anglais).
Ce type d'énoncé a pour objectif de dire à CSS comment se comporter dans certaines circonstances.
Dans notre exemple de mise en page adaptative, nous utiliserons la règle @media pour spécifier des mises en page différentes pour les grands et les petits écrans.
Pour un grand écran (disons 760px et plus), nous utiliserons la mise en page déjà définie.
@media screen and (min-width: 760px) { #conteneur { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: minmax(75px, auto); grid-gap: 10px; max-width: 480px; margin: 0 auto; grid-template-areas: "header header header header" "aside aside main main" "nav nav main main" "section section section section" "footer footer footer footer"; } }
La règle utilisée indique que le CSS entre les accolades est pour un écran d'une largeur de 760px ou plus.
Mais qu'arrive-t-il si la taille de l'écran est inférieure à 760 pixels?
En l'absence d'une mise en page, les éléments sont tout simplement empilés à la verticale.
À moins de prévoir une mise en page particulière...
/* mise en page pour mobile */ #conteneur { ... grid-template-areas: "header header header header" "footer footer footer footer" "main main main main" "main main main main" "aside aside nav nav" "section section section section"; } /* mise en page pour ordinateur de bureau */ @media screen and (min-width: 760px) { #conteneur { ... } }
On constate qu'il est possible de changer non seulement la proportion occupée par un élément, mais aussi sa position.
Dans notre exemple, le pied de page a été déplacé vers le haut (juste sous l'en-tête), parce qu'on suppose ici qu'il contient des informations importantes qui doivent être vues de tous, même par l'utilisateur d'un appareil mobile.
N'hésitez pas à afficher l'exemple, à faire varier la largeur de la fenêtre et à en constater l'effet.