Schauen wir uns eine super leichtgewichtige Methode an, um einen horizontalen Masonry-Effekt für eine Reihe von Fotos beliebiger Größe zu erstellen. Wirf beliebige Fotos hinein, und sie reihen sich Kante an Kante ohne Lücken auf.
Die Lösung ist nicht nur leichtgewichtig, sondern auch ziemlich einfach. Wir verwenden eine unsortierte Liste von Bildern und nur 17 Zeilen CSS, wobei die Schwergewichte flexbox und object-fit sind.
Warum?
Ich habe zwei Hobbys: mein Leben mit Fotos zu dokumentieren und interessante Wege zu finden, CSS-Eigenschaften zu kombinieren, sowohl alte als auch neue.
Vor ein paar Wochen habe ich an XOXO teilgenommen und eine Menge Fotos gemacht, die ich auf eine schöne kleine Auswahl von 39 reduziert habe. Da ich meine Inhalte besitzen möchte, habe ich mich in den letzten Jahren damit beschäftigt, einen einfachen Fotoblog zu erstellen, aber ich konnte nie das Layout perfektionieren, das ich mir vorgestellt hatte: ein einfaches Masonry-Layout, bei dem Fotos Zeilen füllen, während sie ihr Seitenverhältnis beibehalten (denken Sie an Photos.app auf iOS, Google Fotos, Flickr...).

Ich habe recherchiert, ob es leichte, nicht-JavaScript-Optionen gibt, konnte aber nichts finden, das meinen Bedürfnissen entsprach. Angesichts einiger Flugverspätungen begann ich, mit Code herumzuspielen und beschränkte mich darauf, die Dinge so einfach wie möglich zu halten (denn das ist meine Definition von Spaß).
Grundlegender Markup
Da ich im Grunde eine Liste von Bildern erstelle, habe ich mich für eine unsortierte Liste entschieden
<ul>
<li>
<img>
</li>
<!-- ... -->
<li>
<img>
</li>
</ul>
Hoch lebe Flexbox
Dann kamen eine Reihe von Erleuchtungsmomenten
- Flexbox ist großartig, um Zeilen zu füllen, indem die Zellbreite basierend auf dem Zellinhalt bestimmt wird.
- Das bedeutete, dass die Bilder (Quer- oder Hochformat) alle die gleiche Höhe haben mussten.
- Ich könnte
object-fit: cover;verwenden, um sicherzustellen, dass die Bilder die Zellen ausfüllen.
Theoretisch klang das nach einem soliden Plan, und es brachte mir ein Ergebnis, mit dem ich zu etwa 90% zufrieden war.
ul {
display: flex;
flex-wrap: wrap;
}
li {
height: 40vh;
flex-grow: 1;
}
img {
max-height: 100%;
min-width: 100%;
object-fit: cover;
vertical-align: bottom;
}
Hinweis: 40vh schien der beste erste Ansatz für Desktop-Browser zu sein, da es zwei volle Reihen von Fotos in angemessener Größe anzeigte und auf weitere unten hinwies. Dies ermöglichte auch mehr Fotos pro Zeile, was die Seitenverhältnisse dramatisch verbessert.
Dehnungsfähigkeit der letzten Zeile
Das einzige Problem, auf das ich gestoßen bin, ist, dass Flexbox *wirklich* alle Zeilen füllen möchte, und es hat einige seltsame Dinge mit den Seitenverhältnissen der Fotos in der letzten Zeile gemacht. Das ist wahrscheinlich mein am wenigsten geliebter Teil dieses Layouts, aber ich musste am Ende der Liste ein leeres <li> Element hinzufügen.
<ul>
<li>
<img>
</li>
<!-- ... -->
<li>
<img>
</li>
<li></li>
</ul>
Kombiniert mit diesem Stück CSS
li:last-child {
flex-grow: 10;
}
Hinweis: Es gibt keine Wissenschaft hinter der Verwendung von „10“. Bei all meinen Tests lieferte dies die besten Ergebnisse.
Demo
Siehe den Pen
Adaptive Photo Layout von Tim Van Damme (@maxvoltar)
auf CodePen.
Viewport-Optimierung
Bei der Arbeit in verschiedenen Viewport-Orientierungen sind einige Überlegungen zu beachten.
Porträt
Wenn Ihr Viewport höher als breit ist, schränkt dieser Ansatz die Anzahl der Fotos pro Zeile ein, was ihre Seitenverhältnisse beeinträchtigt. Um dies zu lösen, können Sie die Fotozeilen mit dieser einfachen Media Query weniger hoch machen
@media (max-aspect-ratio: 1/1) {
li {
height: 30vh;
}
}
Kurze Bildschirme
Um bei kleinen Geräten im Querformat zu helfen, erhöht die Erhöhung der Höhe von Fotos, um sie so groß wie möglich zu sehen
@media (max-height: 480px) {
li {
height: 80vh;
}
}
Kleinere Bildschirme + Porträt
Die meisten Handys sind nicht breit genug, damit Flexbox richtig funktioniert, ohne die Fotos zu miniaturisieren. Daher habe ich hier darauf verzichtet, mehrere Fotos pro Zeile zu fitting. Dennoch lohnt es sich, hier eine maximale Höhe festzulegen, damit Sie zumindest einen Hinweis auf das nächste Foto in der Liste haben.
@media (max-aspect-ratio: 1/1) and (max-width: 480px) {
ul {
flex-direction: row;
}
li {
height: auto;
width: 100%;
}
img {
width: 100%;
max-height: 75vh;
min-width: 0;
}
}
Da haben wir es!
Dieser Ansatz respektiert die Seitenverhältnisse von Fotos nicht vollständig (aber er kommt nah heran) und führt *gelegentlich* zu einigen seltsamen Ergebnissen, aber ich liebe die Einfachheit und Flexibilität davon absolut. Möchten Sie, dass Ihre Galerie horizontal statt vertikal scrollt? Ein paar Anpassungen ermöglichen Ihnen dies. Gibt es 1.000 Fotos in der Galerie oder nur eines? Alles sieht gut aus. Unsicher bei Seitenverhältnissen? Flexbox ist Ihr bester Freund. Werfen Sie noch einmal einen Blick auf die Demo, wenn Sie es noch nicht getan haben, und lassen Sie mich wissen, was Sie denken!
Bonus
Abhängig von der Größe dieser Fotos kann eine Seite wie diese schnell mehrere Megabyte groß werden. Auf dem Blog, an dem ich arbeite, habe ich loading="lazy" hinzugefügt, um dabei zu helfen. Mit diesem Attribut auf den Bildern werden nur Fotos geladen, wenn Sie beim Scrollen näher an sie herankommen. Es wird derzeit nur in Chrome unterstützt, aber Sie könnten eine eigene, besser unterstützte Technik entwickeln.
Gute Arbeit! Es war sehr einfach, eine Version mit Abständen für ein anderes Gefühl zu forken
Sehr gut, ich habe überlegt, das selbst auszuprobieren, bevor ich diesen Kommentar sehe.
Sehr cool. Sie können das letzte
li, das Ihnen nicht gefällt, entfernen, indem Sieflex-grow:10auf einul:afterPseudo-Element verschiebenSiehe den Pen
Adaptive Photo Layout von Will Anderson (@andwilr)
auf CodePen.
Kein Bedarf für dieses leere
<li></li>am Ende. Sie können ein Pseudo-Element an das<ul>anhängen und es verhält sich wie das letzte Flex-Elementul::after {content:"";
flex-grow: 10;
}
Toll, ich habe gerade versucht, dieses Layout zu erreichen! Ich habe festgestellt, dass das Hinzufügen einer flex-basis zum letzten Element (das Sie meiner Meinung nach durch ein
::afterersetzen können) dazu beitragen kann, dass die letzten Bilder die letzte Zeile füllen.Hallo,
Dies ist eine ziemlich interessante Art, ein schlankes Fotogitter zu erstellen.
Eine Sache jedoch: Anstatt ein leeres li am Ende hinzuzufügen, könnten Sie das after-Element am Raster mit einer Höhe von Null und flex-grow: 10 verwenden.
Die Verwendung von height: 0 hat keine Auswirkung, wenn das Element in eine eigene Zeile verschoben wird, während die Wirkung des Verschiebens der Elemente nach links erhalten bleibt.
Dies sollte die Aufgabe erfüllen, ohne ein zusätzliches leeres Element hinzuzufügen.
Ihr seid alle erstaunlich! Die Verwendung von
::afterist mir total entfallen.Danke fürs Teilen!
Ich habe mit Ihrem Code (und einigen meiner Bilder) gespielt und bemerkt, dass es manchmal vorkommt, dass einige Bilder die Höhe nicht richtig abdecken, sodass Sie den Hintergrund unter dem Bild sehen können. Haben Sie eine Idee, wie ich dieses Verhalten beheben kann?
Ich bin auf dieses Problem nicht gestoßen! Welchen Browser verwenden Sie?
Gibt es eine Möglichkeit, dies in Bootstrap 4 zum Laufen zu bringen? Das Layout funktioniert dort nicht wirklich, wahrscheinlich wegen der Standardstile für <ul> und <li>.
Ich habe Bootstrap nie benutzt (immer mein eigenes System entwickelt)
Hallo – sehr cooles Layout… Frage: Wenn Sie dies in ein WordPress Child-Theme integrieren würden, haben Sie Empfehlungen, welche Dateien Sie ändern oder welche Vorlagen Sie konfigurieren müssten, um ein ähnliches Fotolayout zu erzielen..??..
Das einzige CMS, das ich je benutzt habe, war Textpattern. Und das ist... eine Weile her.
Großartig. Dies hat mich inspiriert zu sehen, wie es auf meiner tatsächlichen Website funktionieren würde. Wie andere habe ich Ränder, Schatten und Rahmen hinzugefügt, bevor ich die Kommentare sah. Ich wollte meine verlinkbar und hoverbar haben und in meinem 75% Hauptinhaltsbereich (mit Bootstrap 4) funktionieren. Ich habe die Vorschläge ul:after und border-radius geklaut. Ergebnisse: [ https://codepen.io/Gene/pen/LYYVPVm ]
Es gibt einige geringfügige Nachteile dieses :cover-Ansatzes, je nach Geschmack – es zoomt und schneidet alles zu (Tipps zur Behebung und :cover weniger?), und Hochformatfotos sind oft halb so groß wie Querformatfotos. Aus diesen Gründen habe ich mich letztendlich entschieden, mein eigenes Raster-basiertes Seitenverhältnis-Galerie mit dem Gelernten aufzupeppen.
Ich liebe immer noch die Idee und diese Beispiele mit minimalem Code. Es erfordert nur Kreativität, sie inmitten von Websites mit Bibliotheken und Stil-Ballast anzuwenden. Ich werde eine Kopie davon für die Verwendung aufbewahren, wo es angebrachter ist! Kompliment-Sandwich!
Das war das Ziel
Cool und sauber. Ich habe dies in eine React-Funktion gewickelt https://codepen.io/mjunaidi/pen/JjjJWoo
Hallo
Schönes Layout.
Wie kann ich alle Bilder aus einem Ordner importieren und sie mit diesem Layout auf der Website anzeigen?
Wenn ich ein Bild im Ordner hinzufüge oder lösche, wird das Bild auch auf der Website hinzugefügt/gelöscht.
Danke für das inspirierende Beispiel. Ich habe dies verwendet, um eine Wand mit aktuellen Uploads zu meinem Flickr-Konto unter https://www.rockland.dk/show/?post=412 zu erstellen. Nichts Besonderes. Ziemlich Kopie/Einfügen Ihres Codes, außer dass es sich um einen Blog mit fester Breite handelt, daher wurden die Viewport-Optimierungen übersprungen. Ich möchte nur Danke sagen, dass Sie das Beispiel geteilt haben (und vielleicht sollte ich mir die Vorschläge zur Verwendung von :after für das zusätzliche nachlaufende li-Element ansehen)...
Schauen Sie sich dieses Bild an, und dasselbe in Ihrem Flex-Beispiel
https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05586_oj8jfo.jpg
Sie werden sehen, dass es vertikal abgeschnitten ist. Ist das zu erwarten?
Hey! Ja, das wäre zu erwarten, da die Demo
object-fit: cover;auf dem img-Element verwendet. Das bewirkt, dass ein Inline-Bild wie ein CSS-Hintergrundbild wirkt und dort abgeschnitten wird, wo sein Container endet.Um auf meinen letzten Kommentar zurückzukommen, das ist bemerkenswert im Beispiel oben auf genau dieser Seite!
Danke dafür.
Aber wie fügt man Beschreibungen direkt unter jedem Bild ein, danke