Autre proposition pour la maçonnerie CSS

L'équipe Chrome souhaite implémenter des mises en page de type maçonnerie sur le Web. Toutefois, nous pensons qu'il serait une erreur de l'implémenter dans la spécification CSS Grid, comme proposé dans le post récent de WebKit. Nous pensons également que le post WebKit s'opposait à une version de la mise en page en maçonnerie que personne ne proposait.

Par conséquent, cet article vise à expliquer pourquoi nous, chez Chrome, avons des inquiétudes concernant l'implémentation de la mise en page en maçonnerie dans la spécification de la mise en page en grille CSS, et à clarifier exactement ce que la proposition de remplacement permet. En résumé :

  • L'équipe Chrome est très désireuse de débloquer la mise en page en grille. Nous savons que c'est quelque chose que les développeurs souhaitent.
  • Ajouter la maçonnerie à la spécification de la grille pose problème pour d'autres raisons que vous considériez ou non la maçonnerie comme une grille.
  • La définition de la maçonnerie en dehors de la spécification de la grille n'empêche pas l'utilisation de plusieurs tailles de canaux pour la maçonnerie, ni l'utilisation de propriétés telles que l'alignement ou les écarts, ni toute autre fonctionnalité utilisée dans la mise en page en grille.

La maçonnerie doit-elle faire partie de la grille ?

L'équipe Chrome pense que la maçonnerie doit être une méthode de mise en page distincte, définie à l'aide de display: masonry (ou d'un autre mot clé si un meilleur nom est choisi). Plus loin dans cet article, vous trouverez des exemples de ce à quoi cela peut ressembler dans le code.

Il existe deux raisons liées pour lesquelles nous pensons que la mise en page en maçonnerie est mieux définie en dehors de la mise en page en grille : les problèmes potentiels de performances de mise en page et le fait que la mise en page en maçonnerie et la mise en page en grille présentent des fonctionnalités qui ont du sens dans une méthode de mise en page, mais pas dans l'autre.

Performances

La grille et la maçonnerie sont opposées en termes de façon dont le navigateur gère la mise à l'échelle et l'emplacement. Lorsqu'une grille est mise en page, tous les éléments sont placés avant la mise en page, et le navigateur sait exactement ce qui se trouve dans chaque canal. Cela permet la mise à l'échelle intrinsèque complexe qui est si utile dans la grille. Avec la mise en page en maçonnerie, les éléments sont placés tels qu'ils sont disposés, et le navigateur ne sait pas combien il y en a dans chaque canal. Ce n'est pas un problème avec tous les canaux de taille intrinsèque ni tous les canaux de taille fixe, mais si vous mélangez des canaux fixes et intrinsèques. Pour contourner le problème, le navigateur doit effectuer une étape de prémise en page en mettant en page chaque élément de toutes les manières possibles pour obtenir des mesures. Avec une grande grille, cela contribuerait à des problèmes de performances de mise en page.

Par conséquent, si vous aviez une mise en page en maçonnerie avec une définition de canal grid-template-columns: 200px auto 200px (ce qui est très courant dans une grille), vous commenceriez à rencontrer des problèmes. Ces problèmes deviennent exponentiels lorsque vous ajoutez des sous-grilles.

On peut affirmer que la plupart des utilisateurs ne rencontreront pas ce problème, mais nous savons déjà que les utilisateurs ont des grilles très grandes. Nous ne voulons pas proposer un produit dont l'utilisation est limitée, alors qu'il existe une autre approche.

Que faire des éléments qui n'ont pas de sens dans chaque méthode de mise en page ?

Lorsque flexbox et grid sont devenus des éléments du CSS, les développeurs ont souvent eu le sentiment qu'ils se comportaient de manière incohérente. L'incohérence qu'il rencontrait était due à des hypothèses anciennes sur le fonctionnement de la mise en page, basée sur la mise en page par bloc. Au fil du temps, les développeurs ont commencé à comprendre les contextes de mise en forme. Lorsque nous passons à un contexte de mise en forme en grille ou en flex, certains éléments se comportent différemment. Par exemple, vous savez que lorsque vous utilisez Flexbox, toutes les méthodes d'alignement ne sont pas disponibles, car Flexbox est unidimensionnel.

Le regroupement de la mise en page en grille rompt ce lien clair entre le contexte de mise en forme et la disponibilité d'éléments tels que les propriétés d'alignement, qui sont définies dans la spécification d'alignement de la boîte par contexte de mise en forme.

Si nous décidons de résoudre le problème de performances décrit précédemment en rendant illégales les définitions de canaux mixtes intrinsèques et fixes dans la mise en page en maçonnerie, vous devrez vous rappeler qu'un modèle très courant pour les mises en page en grille ne fonctionne pas pour la mise en page en maçonnerie.

Il existe également des modèles qui auraient du sens dans la maçonnerie, par exemple grid-template-columns: repeat(auto-fill, max-content), car vous n'avez pas de contraintes croisées, mais vous devez rester non valide dans la grille. Vous trouverez ci-dessous la liste des propriétés dont le comportement est différent ou dont les valeurs valides sont différentes.

  • grid-template-areas: Dans la maçonnerie, vous ne pouvez spécifier que la ligne initiale dans le sens opposé à la maçonnerie.
  • grid-template: l'abréviation doit tenir compte de toutes les différences.
  • Valeurs de dimensionnement des pistes pour grid-template-columns et grid-template-rows en raison de différences de valeurs légales.
  • grid-auto-flow ne s'applique pas à la mise en page en maçonnerie, et masonry-auto-flow ne s'applique pas à la mise en page en grille. Les fusionner créerait des problèmes d'éléments non valides en raison de la méthode de mise en page utilisée.
  • La grille comporte quatre propriétés d'emplacement (grid-column-start, etc.), tandis que la maçonnerie n'en comporte que deux.
  • La grille peut utiliser les six propriétés justify-* et align-*, mais la maçonnerie n'utilise qu'un sous-ensemble, comme Flexbox.

Vous devrez également spécifier ce qui se passe dans tous les nouveaux cas d'erreur causés par les développeurs qui utilisent une valeur non valide dans "grid-with-masonry" ou "grid-without-masonry". Par exemple, vous pouvez utiliser grid-template-columns: masonry ou grid-template-rows: masonry, mais pas les deux à la fois. Que se passe-t-il si vous utilisez les deux en même temps ? Ces informations doivent être spécifiées pour que tous les navigateurs fassent la même chose.

Tout cela devient compliqué d'un point de vue de spécification, maintenant et à l'avenir. Nous devrons nous assurer que tout tient compte de la maçonnerie, et si elle fonctionne ou non dans la maçonnerie. Cela peut également prêter à confusion du point de vue des développeurs. Pourquoi devez-vous garder à l'esprit que, malgré l'utilisation de display: grid, certaines choses ne fonctionnent pas en raison de l'utilisation de la maçonnerie ?

Une autre proposition

Comme indiqué précédemment, l'équipe Chrome souhaite définir la maçonnerie en dehors de la spécification de la grille. Cela ne signifie pas qu'il se limitera à une méthode de mise en page très simple avec des tailles de colonnes identiques. Toutes les démonstrations du post WebKit resteront possibles.

Mise en page classique en maçonnerie

La plupart des gens associent la maçonnerie à une mise en page avec plusieurs colonnes de taille égale. Cela serait défini à l'aide du code CSS suivant, qui nécessite un code moins ligné que la version groupée de la grille équivalente.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1rem;
}

Pistes de taille égale.

Utiliser la mise à l'échelle des canaux de type grille pour différentes largeurs de colonne

Outre le problème mentionné précédemment concernant la taille mixte des canaux intrinsèques et fixes, vous pouvez utiliser toutes les tailles de canaux que vous aimez à partir de la grille. Comme dans l'exemple de l'article de blog WebKit, il s'agit d'un modèle de colonnes étroites et larges répétées.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(8rem, 1fr) minmax(16rem, 2fr)) minmax(8rem, 1fr);
  gap: 1rem;
}

Motif de pistes larges et étroites.

Tailles de canaux supplémentaires pour la mise en page en maçonnerie

Il existe d'autres options de dimensionnement de la piste que nous n'autorisons pas dans la grille, car la grille est une méthode de mise en page bidimensionnelle. Ils seraient utiles en maçonnerie, mais il serait déroutant s'ils ne fonctionnaient pas en grille.

Remplissage automatique des pistes de taille max-content.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, max-content);
  gap: 1rem;
}

Remplissage automatique des canaux de taille auto, qui crée des canaux de la même taille, adaptés automatiquement pour accueillir le plus grand.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
  gap: 1rem;
}

Mise en page en maçonnerie avec des canaux de taille automatique.

Autoriser le contenu à s'étendre sur plusieurs colonnes et placer des éléments dans la mise en page en maçonnerie

Il n'y a aucune raison de ne pas avoir de contenu couvrant plusieurs colonnes dans une spécification de maçonnerie distincte. Cela peut utiliser une propriété masonry-track, qui est un raccourci pour masonry-track-start et masonry-track-end, car vous n'avez qu'une seule dimension pour s'étendre dans une mise en page en maçonnerie.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
}

.span-2 {
  masonry-track: span 2; /* spans two columns */
}

.placed {
  masonry-track: 2 / 5; /* covers tracks 2, 3, and 4 */
}

Mise en page en maçonnerie avec des éléments placés et s'étendant sur plusieurs lignes.

Sous-maçonnerie ou sous-grille avec rails en maçonnerie

Cela peut être pris en charge avec une spécification de maçonnerie distincte, là encore avec la condition que les canaux mixtes de taille intrinsèque et fixe ne soient pas autorisés. Il faudra définir précisément à quoi cela ressemble. Nous ne voyons aucune raison pour que cela ne fonctionne pas.

Conclusion

Nous aimerions arriver à un point où une spécification peut être distribuée de manière interopérable. Toutefois, nous voulons le faire de manière à ce que cela fonctionne bien maintenant et à l'avenir, et que les développeurs puissent s'y fier. Le seul moyen de résoudre les problèmes de performances décrits serait d'aggraver le deuxième problème (à savoir, la présence de parties de grille non conformes dans la maçonnerie). Nous ne pensons pas que ce soit une bonne solution, en particulier lorsqu'il est possible d'avoir toutes les fonctionnalités de grille souhaitées tout en séparant clairement les éléments différents.

Si vous avez des commentaires, rejoignez la discussion sur le problème 9041.

Merci à Bramus, Tab Atkins-Bittner, Una Kravets, Ian Kilpatrick et Chris Harrelson d'avoir examiné ce post et d'avoir participé aux discussions qui l'ont inspiré.