CSS grid : centrez-les tous

Publié par Fabrice le 07 octobre 2020, temps de lecture estimé : 5 minutes Webmastering

CSS Grid : centrez-les tous

Petit exercice de style avec CSS grid : peut-on centrer tous les éléments orphelins d'une grille en responsive ? Oui mais c'est compliqué !

Mettons les choses au point tout de suite : pour ce genre de rendu, l'utilisation de flex avec justify-content: center; est ce qu'il y a de plus approprié, de plus simple et de plus léger. Mais pourquoi faire simple quand on peut faire compliqué !

Centrez-les tous

L'idée de base est venue de l'article de CSS { In Real Life } : Controlling Leftover Grid Items with Pseudo-selectors. Le principe est de combiner last-child, nth-child et nth-last-child pour cibler les éléments orphelins de la dernière ligne de la grille. Le doublement des colonnes (une grille à 5 colonnes devient en fait une grille à 10 colonnes) permet aux blocs de chevaucher 2 colonnes (avec grid-column: span 2;). En utilisant grid-column-end, les éléments ciblés peuvent ainsi être réarrangés sur la grille.
Note : sur la démo CodePen, les éléments orphelins ciblés sont d'une autre couleur.

Mais comme il faut bien compliquer encore une peu les choses, le tout doit, évidemment, être adaptatif à la largeur de l'écran (4 largeurs dans ce cas) :

  • Sur grand écran on a une disposition en colonnes comme ceci : 2 / 3 / 4 / 5
  • Sur les écrans intermédiaires on a respectivement : 2 / 3 / 3 / 4 et 2 / 2 / 2 / 3
  • sur petit écran : 1 seule colonne

Voir la démo sur CodePen

Le code SASS

$bp-small: 767px;
$bp-medium: 1024px;
$bp-large: 1200px;
$grid-gap: 1.2em;

[class^="grid-"] {
	display: grid;
	gap: $grid-gap;
} 
@media (max-width: $bp-small - 1) {
	[class^="grid-"] {
		grid-template-columns: repeat(1, 1fr);
	} 
}
@media (min-width: $bp-small) {
	[class^="grid-"] > * {
		grid-column: span 2;
	}
	.grid-2 {
		grid-template-columns: repeat(4, 1fr);
		> * {			
			// 1 Orphan
			&:last-child:nth-child(odd) {
				grid-column-end: 4;
			}
		}
	}
}
@media (min-width: $bp-small) and (max-width: $bp-medium - 1) {
	.grid-3, .grid-4 {
		grid-template-columns: repeat(4, 1fr);
		> * {			
			// 1 Orphan
			&:last-child:nth-child(odd) {
				grid-column-end: 4;
			}
		}
	}
	.grid-5 {
		grid-template-columns: repeat(6, 1fr);
		> * {		
			// 1 Orphan
			&:last-child:nth-child(3n - 2) {
				grid-column-end: 5;
			}			
			// 2 Orphans
			&:last-child:nth-child(3n - 1) {
				grid-column-end: 6;
			}			
			&:nth-last-child(2):nth-child(3n + 1) {
				grid-column-end: 4;
			}	
		}
	}
}
@media (min-width: $bp-medium) {
	.grid-3 {
		grid-template-columns: repeat(6, 1fr);
		> * {			
			// 1 Orphan
			&:last-child:nth-child(3n - 2) {
				grid-column-end: 5;
			}			
			// 2 Orphans
			&:last-child:nth-child(3n - 1) {
				grid-column-end: 6;
			}			
			&:nth-last-child(2):nth-child(3n + 1) {
				grid-column-end: 4;
			}		
		} 
	}
}
@media (min-width: $bp-medium) and (max-width: $bp-large - 1) {
	.grid-4 {
		grid-template-columns: repeat(6, 1fr);
		> * {			
			// 1 Orphan
			&:last-child:nth-child(3n - 2) {
				grid-column-end: 5;
			}			
			// 2 Orphans
			&:last-child:nth-child(3n - 1) {
				grid-column-end: 6;
			}			
			&:nth-last-child(2):nth-child(3n + 1) {
				grid-column-end: 4;
			}		
		} 
	}
	.grid-5 { 
		grid-template-columns: repeat(8, 1fr);
		> * {			
			// 1 Orphan
			&:last-child:nth-child(4n - 3) {
 				grid-column-end: 6;
			}						
			// 2 Orphans
			&:last-child:nth-child(4n - 2) {
 				grid-column-end: 7;
			}
			&:nth-last-child(2):nth-child(4n + 1) {
				grid-column-end: 5;
			}
			// 3 Orphans
			&:last-child:nth-child(4n - 1) {
 				grid-column-end: 8;
			}
			&:nth-last-child(3):nth-child(4n + 1) {
 				grid-column-end: 4;
			}		
		}
	} 
}
@media (min-width: $bp-large) {
	.grid-4 {
		grid-template-columns: repeat(8, 1fr);
		> * {			
			// 1 Orphan
			&:last-child:nth-child(4n - 3) {
 				grid-column-end: 6;
			}						
			// 2 Orphans
			&:last-child:nth-child(4n - 2) {
 				grid-column-end: 7;
			}
			&:nth-last-child(2):nth-child(4n + 1) {
				grid-column-end: 5;
			}
			// 3 Orphans
			&:last-child:nth-child(4n - 1) {
 				grid-column-end: 8;
			}
			&:nth-last-child(3):nth-child(4n + 1) {
 				grid-column-end: 4;
			}		
		}
	} 
	.grid-5 {
		grid-template-columns: repeat(10, 1fr);
		> * {						
			// 1 Orphan
			&:last-child:nth-child(5n - 4) {
 				grid-column-end: 7;
			}						
			// 2 Orphans
			&:last-child:nth-child(5n - 3) {
 				grid-column-end: 8;
			}
			&:nth-last-child(2):nth-child(5n + 1) {
				grid-column-end: 6;
			}
			// 3 Orphans
			&:last-child:nth-child(5n - 2) {
 				grid-column-end: 9;
			}
			&:nth-last-child(3):nth-child(5n + 1) {
 				grid-column-end: 5;
			}
			// 4 Orphans
			&:last-child:nth-child(5n - 1) {
 				grid-column-end: 10;
			}
			&:nth-last-child(4):nth-child(5n + 1) {
 				grid-column-end: 4;
			}		
		}
	}
}