Je dois mettre en place une structure de maçonnerie assez délabrée. Cependant, pour un certain nombre de raisons, je ne souhaite pas utiliser JavaScript pour le faire.
Paramètres:
il existe une solution triviale à cela qui fonctionne dans les navigateurs modernes, le column-count
propriété.
Le problème avec cette solution est que les éléments sont classés en colonnes:
Bien que j'ai besoin que les éléments soient classés en lignes, au moins approximativement:
Les approches que j'ai essayées ne fonctionnent pas:
display: inline-block
: perd de l’espace vertical.float: left
: lol, no.Maintenant, je pourrais modifier le rendu côté serveur et réorganiser les éléments en divisant le nombre d'éléments par le nombre de colonnes, mais c'est compliqué, source d'erreurs comment les navigateurs décident de scinder la liste d’éléments en colonnes), je voudrais donc l’éviter si possible.
Existe-t-il une magie newfangled flexbox) qui rend cela possible?
Une maçonnerie dynamique 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 sur des lignes horizontales OR). Un élément flexible est limité à 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 des lignes et des colonnes, ce que les éléments flexibles ne peuvent pas faire.
C’est pourquoi flexbox a une capacité limitée de construction de grilles. C’est également une raison pour laquelle le W3C a développé une autre technologie CSS3, Grid Layout .
row wrap
Dans un conteneur flex avec flex-flow: row wrap
, Les éléments flex doivent être renvoyés à une nouvelle lignes.
Cela signifie que un élément flexible ne peut pas être placé sous un autre élément de la même ligne.
Remarquez ci-dessus comment div # 3 retourne ci-dessous div # 1, en créant une nouvelle ligne. Il ne peut pas envelopper sous div # 2.
Par conséquent, lorsque les éléments ne sont pas les plus hauts de la rangée, il reste un espace blanc, créant des espaces disgracieux.
column wrap
Si vous passez à flex-flow: column wrap
, Une mise en page semblable à une grille est plus accessible. Cependant, un conteneur dans la direction des colonnes présente quatre problèmes potentiels dès le départ:
Par conséquent, un conteneur dans la direction des colonnes n'est pas une option dans ce cas, et dans de nombreux autres cas.
La disposition de la 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 bien dans les capacités de Grid.
La largeur et la hauteur des éléments de la grille doivent être connues afin de combler les écarts avec les éléments environnants.
Donc, Grid, qui est le meilleur CSS à offrir pour la construction d’une structure en maçonnerie coulant horizontalement, manque dans ce cas.
En fait, tant qu’une technologie CSS n’est pas en mesure de combler automatiquement les lacunes, CSS n’a généralement pas de solution. Quelque chose comme cela nécessiterait probablement de refondre le document, donc je ne suis pas sûr de son utilité ou de son efficacité.
Vous aurez besoin d'un script.
Les solutions JavaScript ont tendance à utiliser un positionnement absolu, qui supprime les éléments de contenu du flux de documents afin de les réorganiser sans lacunes. Voici deux exemples:
La maçonnerie est une bibliothèque de disposition de grille JavaScript. Cela fonctionne en plaçant les éléments dans une position optimale en fonction de l'espace vertical disponible, un peu comme un maçon plaçant des pierres dans un mur.
source: http://masonry.desandro.com/
Comment construire un site qui fonctionne comme Pinterest
[Pinterest] est vraiment un site cool, mais ce que je trouve intéressant, c'est la façon dont ces tableaux sont disposés ... Donc, le but de ce tutoriel est 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
Pour les dispositions où la largeur et la hauteur des éléments de contenu sont connues, voici une disposition de maçonnerie coulant horizontalement en CSS pur:
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 ça marche
inline-grid
Serait l'autre option)grid-auto-rows
définit la hauteur des lignes générées automatiquement. Dans cette grille, chaque rangée mesure 50 pixels de haut.grid-gap
est un raccourci pour grid-column-gap
Et grid-row-gap
. Cette règle définit un écart de 10 pixels entre éléments de grille. (Cela ne s'applique pas à la zone située entre les articles et le conteneur.)La propriété grid-template-columns
définit la largeur des colonnes explicitement définies.
La notation repeat
définit un modèle de répétition de colonnes (ou de lignes).
La fonction auto-fill
indique à la grille d'aligner autant de colonnes (ou de lignes) que possible sans déborder. le conteneur. (Cela peut créer un comportement similaire à celui de flex-wrap: wrap
De la mise en page.)
La fonction minmax()
définit une plage de tailles 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.
L'unité fr
représente une fraction de l'espace libre dans le conteneur de la grille. C'est comparable à la propriété flex-grow
De flexbox.
Avec grid-row
et span
nous indiquons aux éléments de la grille le nombre de lignes qu’ils doivent couvrir.
Prise en charge du navigateur pour la grille CSS
Voici l'image complète: http://caniuse.com/#search=grid
Fonction de superposition de grille dans Firefox
Dans les outils de développement de Firefox, lorsque vous inspectez le conteneur de grille, la déclaration CSS contient une petite icône de grille. Au clic, il affiche un aperçu 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
C'est une technique récemment découverte faisant appel à flexbox: https://tobiasahlin.com/blog/masonry-with-css/ .
L'article a du sens pour moi, mais je n'ai pas essayé de l'utiliser, donc je ne sais pas s'il existe des avertissements, autres que ceux mentionnés dans la réponse de Michael.
Voici un exemple tiré de l'article, utilisant la propriété order
, associée à :nth-child
.
Extrait de pile
.container {
display: flex;
flex-flow: column wrap;
align-content: space-between;
/* Your container needs a fixed height, and it
* needs to be taller than your tallest column. */
height: 960px;
/* Optional */
background-color: #f7f7f7;
border-radius: 3px;
padding: 20px;
width: 60%;
margin: 40px auto;
counter-reset: items;
}
.item {
width: 24%;
/* Optional */
position: relative;
margin-bottom: 2%;
border-radius: 3px;
background-color: #a1cbfa;
border: 1px solid #4290e2;
box-shadow: 0 2px 2px rgba(0,90,250,0.05),
0 4px 4px rgba(0,90,250,0.05),
0 8px 8px rgba(0,90,250,0.05),
0 16px 16px rgba(0,90,250,0.05);
color: #fff;
padding: 15px;
box-sizing: border-box;
}
/* Just to print out numbers */
div.item::before {
counter-increment: items;
content: counter(items);
}
/* Re-order items into 3 rows */
.item:nth-of-type(4n+1) { order: 1; }
.item:nth-of-type(4n+2) { order: 2; }
.item:nth-of-type(4n+3) { order: 3; }
.item:nth-of-type(4n) { order: 4; }
/* Force new columns */
.break {
flex-basis: 100%;
width: 0;
border: 1px solid #ddd;
margin: 0;
content: "";
padding: 0;
}
body { font-family: sans-serif; }
h3 { text-align: center; }
<div class="container">
<div class="item" style="height: 140px"></div>
<div class="item" style="height: 190px"></div>
<div class="item" style="height: 170px"></div>
<div class="item" style="height: 120px"></div>
<div class="item" style="height: 160px"></div>
<div class="item" style="height: 180px"></div>
<div class="item" style="height: 140px"></div>
<div class="item" style="height: 150px"></div>
<div class="item" style="height: 170px"></div>
<div class="item" style="height: 170px"></div>
<div class="item" style="height: 140px"></div>
<div class="item" style="height: 190px"></div>
<div class="item" style="height: 170px"></div>
<div class="item" style="height: 120px"></div>
<div class="item" style="height: 160px"></div>
<div class="item" style="height: 180px"></div>
<div class="item" style="height: 140px"></div>
<div class="item" style="height: 150px"></div>
<div class="item" style="height: 170px"></div>
<div class="item" style="height: 170px"></div>
<span class="item break"></span>
<span class="item break"></span>
<span class="item break"></span>
</div>