La Cascade

Un peu de tout sur CSS, HTML, SVG et JS,traduit du web anglophone
Rechercher

Grid et Flexbox, le duo gagnant

par Chen Hui Jing, 5 mars 2017, cssgrid, css, flexbox, design, article original paru le 2 mars 2017 dans le blog de Chen Hui Jing

CSS Grid et Flexbox sont faits pour fonctionner ensemble. Grid pour l'organisation générale, Flexbox pour les ajustements spécifiques. Chen Hui Jing le démontre avec un exemple magistral (et quelques bonus).


Plongée profonde dans CSS Grid

Vous vous rappelez la réponse de Rachel Andrew à la question "utiliser CSS Grid ou Flexbox" ? Sinon vous pouvez regarder la vidéo (en anglais).

Flexbox est fait pour les layouts unidimensionnels, CSS Grid est fait pour les layouts en 2 dimensions

Rachel Andrew

Je suis sûre que beaucoup l'ont réalisé avant moi, mais avant ma relation torride d'un mois avec CSS Grid je ne m'étais pas rendue compte à quel point Flexbox et Grid sont faits pour s'entendre. C'était quelque chose du genre oeufs et bacon, pomme et cannelle, beurre de cacahuète et confiture — ah ça y est, j'ai faim tout d'un coup.

Vous avez peut-être vu que j'ai apporté une contribution au CSS Reference de Codrops. Sérieux, c'est une des meilleures choses qui me soit arrivées en 2016. Une des entrées qui manquaient encore était CSS Grid. Avant de m'y mettre, j'avais juste bricolé un peu avec Grid en construisant un prototype pour Penang Hokkien utilisant Grid, histoire de voir si le mode vertical fonctionnerait mieux qu'avec Flexbox.

Et puis je me suis attelée au boulot et j'ai écrit l'article.

3 semaines plus tard, j'avais l'impression d'avoir fusionné avec Metal Cactuar puissance maximum (désolé, Final Fantasy fait partie de ma vie), autrement dit j'étais passé au niveau supérieur.

J'ai passé beaucoup de temps à éplucher la spécification, la lecture des articles de Manuel Rego Casasnovas sur CSS Grid m'a beaucoup aidé ainsi que l'antisèche de Rachel Andrew à un moment de grande confusion.

Un conseil : quand vous essayez d'apprendre une nouvelle propriété CSS, ayez toujours sous la main un template vide avec lequel vous pourrez expérimenter. Ça m'a vraiment été utile avec une propriété aussi nouvelle que Grid. Je sais, il y a aussi Codepen et tout, mais rien ne vaut un template vierge pour une expérimentation libre de toute distraction.

Exemples et démos

Pour analyser toutes les propriétés, j'ai commencé à construire des grilles très basiques, juste pour voir le fonctionnement des valeurs de propriétés. Si vous avez regardé la syntaxe de grid-template-rows dans la spécification, vous savez que ce n'était pas une tâche triviale. Grid lui-même n'est compliqué à apprendre. Mais comme il a été conçu pour être flexible et puissant, il vous faudra un peu de temps pour rentrer dans son fonctionnement.

Quelques-unes des grilles basiques se sont transformées en démos. Certaines trouvaient leur inspiration dans des conversations avec des membres du CSS Layout Club. J'ai aussi glané quelques idées dans le cours de Coursera Ideas from the History of Graphic Design, il y a plein de belles choses (la semaine dernière était consacrée au Bauhaus).

Je suis tombée sur cette page de Malerei, Fotografie, Film par László Moholy-Nagy, dont la mise en page utilisait une grille originale et l'idée m'est venue qu'on pouvait peut-être la réaliser en CSS...

grille texte et images, texte horizontal et vertical, symboles, fortes séparations
Page 126 de Malerei, Fotografie, Film

Le Bauhaus dans mon navigateur

Voici comment j'ai procédé. J'ai dessiné les lignes de la grille par-dessus l'image en utilisant Sketch, de façon à me faire une idée du nombre de colonnes nécessaires. Dans cet exemple, c'était 1 large colonne suivie de 5 colonnes plus étroites de largeur égale, et j'ai laissé ensuite le navigateur se débrouiller avec la hauteur des rangées.

.grid {
  display: grid;
  grid-template-columns: 30% 9% 9% 9% 9% 9%;
  justify-content: center; /* pour justifier la grille au centre du container */
}

Ensuite, il y a eu tout le code de placement avec les propriétés grid-row et grid-column. Mais si vous regardez à nouveau l'image originale, vous verrez que le contenu de chaque cellule a son propre alignement. Par exemple, celui de la première cellule est à droite, celui de la deuxième est en bas à gauche, etc.

👉🏿 NdT : pour consulter les définitions et utilisation des propriétés, voyez l'article CSS Grid Layout, guide complet).

Mon premier réflexe, vu que j'avais cet alignement de boîtes, a été d'appliquer justify-self et align-self là où c'était nécessaire, pour ajuster les positions de contenu à l'intérieur de chaque cellule. Bien tenté, mais à côté... Le problème est que ces deux propriétés affectent la quantité d'espace occupée par la cellule.

Le design du Bauhaus présente des bordures noires très frappantes autour de chaque cellule. La propriété border s'applique à l'item de grille. Toute propriété d'alignement de grille autre que stretch adaptera la dimension de l'item grid à son contenu. Toute bordure appliquée à un item grid s'adaptera au contenu de l'item, par conséquent je ne pouvais pas procéder ainsi.

les bordures sont sur les items, mais les dimensions de l'item ne sont pas celles de la cellule
Ce ne sont pas les bordures souhaitées !

Flexbox à la rescousse

Par défaut, tous les items grid se comportent comme si leur alignement avait été réglé sur stretch sur chaque axe. J'ai donc laissé tomber, pour permettre à la grille de ressembler à une grille, et à la place, j'ai appliqué display: flex à l'item grid, ce qui m'a permis d'utiliser les propriétés d'alignement flex sur le container flex, pour positionner le contenu de mon item grid.

les bordures correspondent aux lignes horizontales et verticales de la grille, et ne recouvrent pas les items lorsque ceux-ci s'étendent sur plusieurs cellules
Ah voilà, cette fois-ci c'est bon.
.grid__item:nth-child(5) {
  grid-row: 3 / 5;
  border-right: 1em solid;
  padding: 1em;

  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
}

Le code ressemble à ce qui précède, mais ce que je veux souligner avant tout c'est qu'il s'agit d'une formidable technique pour la mise en page. Grid pour l'organisation générale, et Flexbox pour les ajustements spécifiques. Voici ce que ça donne sur Codepen si vous voulez voir le résultat final.

voir le Pen Malerei, Fotografie, Film (pg. 126) de Chen Hui Jing dans CodePen

Bonus : réaliser des formes en CSS

À part les deux photos, tout ce qui est sur la page est réalisé en CSS, autrement dit la flèche et la roue dentée sont des div auxquelles j'ai appliqué des styles. J'aime faire des formes en CSS, avec une div unique si possible. Il suffit pour cela de quelques propriétés pratiques, box-shadow, border et les pseudo-éléments.

La flèche

Les flèches sont assez simples à réaliser. Il vous faut juste un pseudo-élément pour la pointe. Le corps de la flèche est une simple div à laquelle on donne une position: relative de façon à positionner la pointe par rapport au corps. La pointe est un triangle, qu'on peut réaliser grâce à l'astuce de la bordure.

.arrow {
  width: 0.5em;
  height: 65%;
  background-color: #000;
  position: relative;

  &::after {
    display: block;
    content: '';
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: -1em;
    border-style: solid;
    border-width: 1em 1em 0 1em;
    border-color: #000 transparent transparent transparent;
  }
}

La roue dentée

Là, c'est un peu plus compliqué. Le corps de la roue est un cercle, réalisé via border-radius: 50%, mais les dents vont nous demander un peu de travail. Je n'ai pas pu le faire avec une seule div cette fois-ci (mais si quelqu'un y arrive, contactez-moi). J'ai ajouté une div interne. La bonne nouvelle c'est que toutes les dents ont une forme identique, donc l'astuce box-shadow peut être utilisée ici.

.gear {
  height: 5em;
  width: 5em;
  background-color: #000;
  border-radius: 50%;
  position: relative;

  &::before,
  &::after {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: block;
    content: '';
  }

  &::before {
    height: 3em;
    width: 1em;
    box-shadow: 0em -3em 0em 0em #000, 0em 3em 0 0em #000;
  }

  &::after {
    height: 1em;
    width: 3em;
    box-shadow: 3em 0 0em 0em #000, -3em 0 0 0em #000;
  }
}

Le corps de la roue et les 4 dents directionnées comme les aiguilles d'une boussole ont été réalisées avec une seule div et 2 pseudo-éléments. Pour les 4 autres dents, j'ai utilisé la div intérieure avec des pseudo-éléments et fait tourner les box-shadow. Je dois toujours résoudre le problème de transform-origin car je trouve qu'il y a encore une certaine asymétrie.

.inner-gear {
  height: 2em;
  width: 2em;
  border-radius: 50%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #e1e1d5;

  &::before,
  &::after {
    position: absolute;
    display: block;
    content: '';
  }

  &::before {
    height: 3em;
    width: 1em;
    box-shadow: 0em -3em 0em 0em #000, 0em 3em 0 0em #000;
    transform: rotate(45deg);
    transform-origin: (75% 75%);
  }

  &::after {
    height: 1em;
    width: 3em;
    box-shadow: 3em 0 0em 0em #000, -3em 0 0 0em #000;
    transform: rotate(45deg);
    transform-origin: (25% 75%);
  }
}

Conclusion

CSS Grid est vraiment génial, et nous sommes nombreux à le penser. Jen Simmons a compilé une liste de bonnes ressources Grid, faites un tour sur Learn CSS Grid et essayez de construire quelque chose avec Grid. Vous ne le regretterez pas !

Autres ressources externes

Articles de Chen Hui Jing traduits dans La Cascade

Voir la page de Chen Hui Jing et la liste de ses articles dans La Cascade.
Article original paru le 2 mars 2017 dans le blog de Chen Hui Jing
Traduit avec l'aimable autorisation du blog de Chen Hui Jing et de Chen Hui Jing.
Copyright le blog de Chen Hui Jing © 2017