Mise à jour de 2021
CSS Grid Layout Level 3 comprend une masonry
fonction.
Le code ressemblera à ceci :
grid-template-rows: masonry
grid-template-columns: masonry
Depuis mars 2021, il n'est disponible que dans Firefox (après avoir activé le drapeau).
fin de la mise à jour ; réponse originale ci-dessous
Flexbox
Une mise en page dynamique de type "masonry" n'est pas possible avec Flexbox, du moins pas de manière propre et efficace.
Flexbox est un système de mise en page unidimensionnel. Cela signifie qu'il peut aligner des éléments le long de lignes horizontales OU verticales. Un élément Flexbox est confiné à sa ligne ou à sa colonne.
Un véritable système de grille est bidimensionnel, ce qui signifie qu'il peut aligner des éléments le long de lignes horizontales ET verticales. Les éléments de contenu peuvent s'étendre simultanément sur les lignes et les colonnes, ce qui est impossible pour les éléments flexibles.
C'est pourquoi flexbox a une capacité limitée pour construire des grilles. C'est aussi une raison pour laquelle le W3C a développé une autre technologie CSS3, Disposition de la grille .
row wrap
Dans un conteneur flex avec flex-flow: row wrap
les articles flexibles doivent être emballés dans le nouveau rangées .
Cela signifie que un élément flexible ne peut pas s'enrouler sous un autre élément de la même ligne .
Remarquez ci-dessus comment div #3 enveloppes ci-dessous div #1 en créant une nouvelle ligne. Il ne peut pas s'enrouler sous div #2 .
Par conséquent, lorsque les éléments ne sont pas les plus hauts de la rangée, il reste des espaces blancs, ce qui crée des lacunes inesthétiques.
column wrap
Si vous passez à flex-flow: column wrap
une mise en page en forme de grille est plus facile à réaliser. Cependant, un conteneur orienté colonne présente d'emblée quatre problèmes potentiels :
- Les éléments Flex s'écoulent verticalement, et non horizontalement (comme dans le cas présent).
- Le conteneur se développe horizontalement, et non verticalement (comme la mise en page de Pinterest).
- Il faut que le conteneur ait une hauteur fixe, afin que les articles sachent où s'emballer.
- À l'heure où nous écrivons ces lignes, il présente un défaut dans tous les principaux navigateurs où le conteneur ne s'étend pas pour accueillir des colonnes supplémentaires .
Par conséquent, un conteneur orienté colonne n'est pas une option dans ce cas, et dans de nombreux autres cas.
Grille CSS avec des dimensions d'éléments non définies
La disposition en grille serait une solution parfaite à votre problème. si les différentes hauteurs des éléments de contenu pouvaient être prédéterminées . Toutes les autres exigences sont tout à fait dans les limites des capacités de Grid.
La largeur et la hauteur des éléments de la grille doivent être connues afin de pouvoir fermer les espaces avec les éléments environnants.
Ainsi, Grid, qui est ce que CSS a de mieux à offrir pour construire une mise en page de type maçonnerie à flux horizontal, n'est pas à la hauteur dans ce cas.
En fait, jusqu'à l'arrivée d'une technologie CSS capable de combler automatiquement les lacunes, les CSS en général n'ont pas de solution. Une telle solution nécessiterait probablement de refondre le document, et je ne suis donc pas sûr de son utilité ou de son efficacité.
Vous aurez besoin d'un script.
Les solutions JavaScript ont tendance à utiliser le positionnement absolu, qui supprime les éléments de contenu du flux de documents afin de les réorganiser sans discontinuité. Voici deux exemples :
Masonry est une bibliothèque de mise en page de grille JavaScript. Elle fonctionne en plaçant les éléments dans une position optimale en fonction de l'espace vertical disponible. l'espace vertical disponible, un peu comme un maçon qui place des pierres dans un mur.
source : http://masonry.desandro.com/
Pinterest] est un site vraiment cool, mais ce que je trouve intéressant, c'est la façon dont ces pinboards sont disposés... Le but de ce tutoriel est donc de recréer nous-mêmes cet effet de bloc réactif...
source : https://benholland.me/javascript/2012/02/20/how-to-build-a-site-that-works-like-pinterest.html
Grille CSS avec des dimensions d'éléments définies
Pour les mises en page dont la largeur et la hauteur des éléments de contenu sont connues, voici une mise en page en maçonnerie à flux horizontal en pur CSS :
grid-container {
display: grid; /* 1 */
grid-auto-rows: 50px; /* 2 */
grid-gap: 10px; /* 3 */
grid-template-columns: repeat(auto-fill, minmax(30%, 1fr)); /* 4 */
}
[short] {
grid-row: span 1; /* 5 */
background-color: green;
}
[tall] {
grid-row: span 2;
background-color: crimson;
}
[taller] {
grid-row: span 3;
background-color: blue;
}
[tallest] {
grid-row: span 4;
background-color: gray;
}
grid-item {
display: flex;
align-items: center;
justify-content: center;
font-size: 1.3em;
font-weight: bold;
color: white;
}
<grid-container>
<grid-item short>01</grid-item>
<grid-item short>02</grid-item>
<grid-item tall>03</grid-item>
<grid-item tall>04</grid-item>
<grid-item short>05</grid-item>
<grid-item taller>06</grid-item>
<grid-item short>07</grid-item>
<grid-item tallest>08</grid-item>
<grid-item tall>09</grid-item>
<grid-item short>10</grid-item>
<grid-item tallest>etc.</grid-item>
<grid-item tall></grid-item>
<grid-item taller></grid-item>
<grid-item short></grid-item>
<grid-item short></grid-item>
<grid-item short></grid-item>
<grid-item short></grid-item>
<grid-item tall></grid-item>
<grid-item short></grid-item>
<grid-item taller></grid-item>
<grid-item short></grid-item>
<grid-item tall></grid-item>
<grid-item short></grid-item>
<grid-item tall></grid-item>
<grid-item short></grid-item>
<grid-item short></grid-item>
<grid-item tallest></grid-item>
<grid-item taller></grid-item>
<grid-item short></grid-item>
<grid-item tallest></grid-item>
<grid-item tall></grid-item>
<grid-item short></grid-item>
</grid-container>
Comment cela fonctionne
-
Établir un conteneur de grille au niveau du bloc. (
inline-grid
serait l'autre option)
- Le site
grid-auto-rows
définit la hauteur des lignes générées automatiquement. Dans cette grille, chaque ligne a une hauteur de 50px.
- Le site
grid-gap
est un raccourci pour grid-column-gap
et grid-row-gap
. Cette règle fixe un écart de 10px entre éléments de la grille. (Elle ne s'applique pas à la zone située entre les éléments et le conteneur).
- Le site
grid-template-columns
définit la largeur des colonnes explicitement définies.
Le site repeat
définit un motif de colonnes (ou de lignes) répétitives.
Le site auto-fill
indique à la grille d'aligner autant de colonnes (ou de lignes) que possible sans faire déborder le conteneur. (Cela peut créer un comportement similaire à celui de la fonction Flex Layout flex-wrap: wrap
.)
Le site minmax()
définit une plage de taille minimale et maximale pour chaque colonne (ou ligne). Dans le code ci-dessus, la largeur de chaque colonne sera au minimum de 30% du conteneur et au maximum de l'espace libre disponible.
Le site fr
unité représente une fraction de l'espace libre dans le conteneur de la grille. Elle est comparable à la fonction flex-grow
propriété.
- Avec
grid-row
et span
nous indiquons aux éléments de la grille sur combien de lignes ils doivent s'étendre.
Prise en charge des grilles CSS par les navigateurs
- Chrome - prise en charge complète à partir du 8 mars 2017 (version 57).
- Firefox - support complet à partir du 6 mars 2017 (version 52)
- Safari - prise en charge complète à partir du 26 mars 2017 (version 10.1).
- Edge - prise en charge complète à partir du 16 octobre 2017 (version 16).
- IE11 - pas de prise en charge de la spécification actuelle ; prise en charge d'une version obsolète
Voici le tableau complet : http://caniuse.com/#search=grid
Fonction de superposition de la grille dans Firefox
Dans les outils de développement de Firefox, lorsque vous inspectez le conteneur de la grille, une petite icône de grille apparaît dans la déclaration CSS. En cliquant dessus, elle affiche un contour de votre grille sur la page.
Plus de détails ici : https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts
8 votes
Je ne vois pas de moyen qui ne dépende pas de hauteurs prédéfinies. Si vous reconsidérez JS, jetez un coup d'œil à stackoverflow.com/questions/13518653/ où j'implémente une telle solution qui est assez simple.
4 votes
Je réalise que vous avez dit "uniquement CSS". Je veux juste mentionner que Masonry ne nécessite plus jQuery - la bibliothèque réduite est moins de 8kb - et peut être initialisé avec le html seul. À titre de référence jsfiddle.net/wp7kuk1t
1 votes
Si vous pouvez déterminer la hauteur des éléments à l'avance, en connaissant la hauteur de ligne, la taille de la police (vous devrez utiliser une police spécifique et effectuer des calculs astucieux), la hauteur de l'image, la marge verticale et le remplissage, vous pouvez le faire. Sinon, vous ne pouvez pas le faire en utilisant uniquement CSS. Vous pourriez également utiliser quelque chose comme PhantomJS pour effectuer un pré-rendu de chaque élément et obtenir la hauteur de cet élément, mais cela entraînerait une surcharge/latence significative.