In einem früheren Artikel habe ich mich mit der Fähigkeit von CSS Grid befasst, komplexe Layouts mit seinen automatischen Platzierungsfähigkeiten zu erstellen. Ich habe dies in einem anderen Artikel noch weiter vorangetrieben, der einen Zoom-Hover-Effekt auf Bilder in einem Grid-Layout hinzufügte. Diesmal möchte ich mich mit einer anderen Art von Grid beschäftigen, einem, das mit Formen arbeitet.
Was zum Beispiel, wenn die Bilder nicht perfekt quadratisch sind, sondern stattdessen die Form von Sechsecken oder Rauten haben? Spoiler-Alarm: Wir können das schaffen. Tatsächlich werden wir CSS Grid-Techniken, die wir bereits besprochen haben, kombinieren und etwas CSS clip-path und mask Magie einbringen, um schicke Bilder-Grids für fast jede erdenkliche Form zu erstellen!
Beginnen wir mit etwas Markup
Die meisten Layouts, die wir uns ansehen werden, mögen auf den ersten Blick einfach zu erreichen sein, aber die Herausforderung besteht darin, sie mit demselben HTML-Markup zu realisieren. Wir könnten viele Wrapper, divs und dergleichen verwenden, aber das Ziel dieses Beitrags ist es, denselben und kleinstmöglichen HTML-Code zu verwenden und trotzdem all die verschiedenen Grids zu erhalten, die wir wollen. Ist CSS schließlich nicht dazu da, Styling und Markup zu trennen? Unser Styling sollte nicht vom Markup abhängen und umgekehrt.
Damit gesagt, fangen wir damit an
<div class="gallery">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<!-- as many times as we want -->
</div>
Ein Container mit Bildern ist alles, was wir hier brauchen. Nichts weiter!
CSS-Grid aus Sechsecken
Dies wird auch manchmal als "Waben"-Grid bezeichnet.
Es gibt bereits viele andere Blogbeiträge, die zeigen, wie das gemacht wird. Verdammt, ich habe einen hier auf CSS-Tricks geschrieben! Dieser Artikel ist immer noch gut und geht sehr tief auf die Erstellung eines responsiven Layouts ein. Aber für diesen speziellen Fall werden wir uns auf einen viel einfacheren CSS-Ansatz verlassen.
Zuerst wenden wir clip-path auf die Bilder an, um die sechseckige Form zu erzeugen, und platzieren sie alle im selben Grid-Bereich, damit sie sich überlappen.
.gallery {
--s: 150px; /* controls the size */
display: grid;
}
.gallery > img {
grid-area: 1/1;
width: var(--s);
aspect-ratio: 1.15;
object-fit: cover;
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0 50%);
}

clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0 50%)Noch nichts Besonderes. Alle Bilder sind sechseckig und übereinander. Es sieht also so aus, als hätten wir nur ein einziges sechseckiges Bildelement, aber es sind eigentlich sieben.
Der nächste Schritt ist die Anwendung einer Transformation auf die Bilder, um sie korrekt auf dem Grid zu platzieren.

Beachten Sie, dass wir möchten, dass eines der Bilder im Zentrum bleibt. Die anderen werden mithilfe von CSS translate und guter alter Geometrie darum herum platziert. Hier sind die Mock-Formeln, die ich für jedes Bild im Grid entwickelt habe
translate((height + gap)*sin(0deg), (height + gap)*cos(0))
translate((height + gap)*sin(60deg), (height + gap)*cos(60deg))
translate((height + gap)*sin(120deg), (height + gap)*cos(120deg))
translate((height + gap)*sin(180deg), (height + gap)*cos(180deg))
translate((height + gap)*sin(240deg), (height + gap)*cos(240deg))
translate((height + gap)*sin(300deg), (height + gap)*cos(300deg))
Nach einigen Berechnungen und Optimierungen (überspringen wir diesen langweiligen Teil, richtig?) erhalten wir das folgende CSS
.gallery {
--s: 150px; /* control the size */
--g: 10px; /* control the gap */
display: grid;
}
.gallery > img {
grid-area: 1/1;
width: var(--s);
aspect-ratio: 1.15;
object-fit: cover;
clip-path: polygon(25% 0%, 75% 0%, 100% 50% ,75% 100%, 25% 100%, 0 50%);
transform: translate(var(--_x,0), var(--_y,0));
}
.gallery > img:nth-child(1) { --_y: calc(-100% - var(--g)); }
.gallery > img:nth-child(7) { --_y: calc( 100% + var(--g)); }
.gallery > img:nth-child(3),
.gallery > img:nth-child(5) { --_x: calc(-75% - .87*var(--g)); }
.gallery > img:nth-child(4),
.gallery > img:nth-child(6) { --_x: calc( 75% + .87*var(--g)); }
.gallery > img:nth-child(3),
.gallery > img:nth-child(4) { --_y: calc(-50% - .5*var(--g)); }
.gallery > img:nth-child(5),
.gallery > img:nth-child(6) { --_y: calc( 50% + .5*var(--g)); }
Vielleicht ist das einfacher, wenn wir echte trigonometrische Funktionen in CSS bekommen!
Jedes Bild wird durch die Variablen --_x und --_y verschoben, die auf diesen Formeln basieren. Nur das zweite Bild (nth-child(2)) ist in keinem Selektor definiert, da es das in der Mitte ist. Es kann jedes Bild sein, wenn Sie eine andere Reihenfolge wählen. Hier ist die Reihenfolge, die ich verwende

Mit nur wenigen Codezeilen erhalten wir ein cooles Bilder-Grid. Dazu habe ich den Bildern einen kleinen Hover-Effekt hinzugefügt, um es schicker zu machen.
Rate mal? Wir können ein weiteres sechseckiges Grid erhalten, indem wir einfach ein paar Werte aktualisieren.
Wenn Sie den Code überprüfen und mit dem vorherigen vergleichen, werden Sie feststellen, dass ich einfach die Werte innerhalb von clip-path vertauscht und zwischen --x und --y gewechselt habe. Das ist alles!
CSS-Grid aus Rauten
Raute ist ein so schickes Wort für ein Quadrat, das um 45 Grad gedreht ist.
Dasselbe HTML, erinnern Sie sich? Zuerst definieren wir in CSS ein 2×2-Grid aus Bildern
.gallery {
--s: 150px; /* controls the size */
display: grid;
gap: 10px;
grid: auto-flow var(--s) / repeat(2, var(--s));
place-items: center;
}
.gallery > img {
width: 100%;
aspect-ratio: 1;
object-fit: cover;
}
Das erste, was Ihnen vielleicht ins Auge fällt, ist die Eigenschaft grid. Sie wird ziemlich selten verwendet, ist aber super hilfreich, da sie eine Kurzschreibweise ist, mit der Sie ein vollständiges Grid in einer einzigen Deklaration definieren können. Es ist nicht die intuitivste – und ganz zu schweigen von der Lesbarkeit – Eigenschaft, aber wir sind hier, um neue Dinge zu lernen und zu entdecken, also lassen Sie uns sie verwenden, anstatt all die einzelnen Grid-Eigenschaften aufzuschreiben.
grid: auto-flow var(--s) / repeat(2,var(--s));
/* is equivalent to this: */
grid-template-columns: repeat(2, var(--s));
grid-auto-rows: var(--s);
Dies definiert zwei Spalten, die der Variablen --s entsprechen, und setzt die Höhe aller Zeilen ebenfalls auf --s. Da wir vier Bilder haben, erhalten wir automatisch ein 2×2-Grid.
Hier ist eine andere Möglichkeit, wie wir es hätten schreiben können
grid-template-columns: repeat(2, var(--s));
grid-template-rows: repeat(2, var(--s));
... was mit der Kurzschreibweise grid reduziert werden kann
grid: repeat(2,var(--s)) / repeat(2,var(--s));
Nachdem wir das Grid eingerichtet haben, drehen wir es und die Bilder mit CSS transforms und erhalten dies
Beachten Sie, wie ich beide um 45deg, aber in entgegengesetzter Richtung drehe.
.gallery {
/* etc. */
transform: rotate(45deg);
}
.gallery > img {
/* etc. */
transform: rotate(-45deg);
}
Das Drehen der Bilder in die negative Richtung verhindert, dass sie sich mit dem Grid drehen, sodass sie gerade bleiben. Jetzt wenden wir einen clip-path an, um eine Rautenform daraus auszuschneiden.

clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%)Wir sind fast fertig! Wir müssen die Größe des Bildes korrigieren, damit es zusammenpasst. Andernfalls sind sie so weit voneinander entfernt, dass es nicht wie ein Grid von Bildern aussieht.

Das Bild befindet sich innerhalb der Grenzen des grünen Kreises, der der einbeschriebene Kreis des Grid-Bereichs ist, in dem das Bild platziert ist. Was wir wollen, ist, das Bild größer zu machen, damit es in den roten Kreis passt, der der umbeschriebene Kreis des Grid-Bereichs ist.
Keine Sorge, ich werde keine langweilige Geometrie mehr einführen. Alles, was Sie wissen müssen, ist, dass das Verhältnis zwischen dem Radius jedes Kreises die Quadratwurzel von 2 (sqrt(2)) ist. Das ist der Wert, den wir brauchen, um die Größe unserer Bilder zu erhöhen, um den Bereich zu füllen. Wir werden 100%*sqrt(2) = 141% verwenden und fertig!
.gallery {
--s: 150px; /* control the size */
display: grid;
grid: auto-flow var(--s) / repeat(2,var(--s));
gap: 10px;
place-items: center;
transform: rotate(45deg);
}
.gallery > img {
width: 141%; /* 100%*sqrt(2) = 141% */
aspect-ratio: 1;
object-fit: cover;
transform: rotate(-45deg);
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
Wie beim Sechseck-Grid können wir die Dinge mit diesem schönen Zoom-Hover-Effekt schicker gestalten
CSS-Grid aus dreieckigen Formen
Sie wissen wahrscheinlich schon, dass der große Trick darin besteht, den clip-path herauszufinden, um die gewünschten Formen zu erhalten. Für dieses Grid hat jedes Element seinen eigenen clip-path-Wert, während die letzten beiden Grids mit einer einheitlichen Form gearbeitet haben. Diesmal ist es also so, als würden wir mit ein paar verschiedenen dreieckigen Formen arbeiten, die zusammen ein rechteckiges Grid von Bildern bilden.


Wir platzieren sie in einem 3×2-Grid mit dem folgenden CSS
.gallery {
display: grid;
gap: 10px;
grid-template-columns: auto auto auto; /* 3 columns */
place-items: center;
}
.gallery > img {
width: 200px; /* controls the size */
aspect-ratio: 1;
object-fit: cover;
}
/* the clip-path values */
.gallery > img:nth-child(1) { clip-path: polygon(0 0, 50% 0, 100% 100% ,0 100%); }
.gallery > img:nth-child(2) { clip-path: polygon(0 0, 100% 0, 50% 100%); }
.gallery > img:nth-child(3) { clip-path: polygon(50% 0, 100% 0, 100% 100%, 0 100%); }
.gallery > img:nth-child(4) { clip-path: polygon(0 0, 100% 0, 50% 100%, 0 100%); }
.gallery > img:nth-child(5) { clip-path: polygon(50% 0, 100% 100%, 0% 100%); }
.gallery > img:nth-child(6) { clip-path: polygon(0 0, 100% 0 ,100% 100%, 50% 100%); } }
Hier ist, was wir bekommen
Der letzte Schliff besteht darin, die Breite der mittleren Spalte auf 0 zu setzen, um die Abstände zwischen den Bildern zu beseitigen. Das gleiche Problem mit den Abständen hatten wir beim Rauten-Grid, aber mit einem anderen Ansatz für die verwendeten Formen.
grid-template-columns: auto 0 auto;
Ich musste mit den clip-path-Werten herumspielen, um sicherzustellen, dass sie alle gut zusammenpassen wie ein Puzzle. Die Originalbilder überlappen sich, wenn die mittlere Spalte keine Breite hat, aber nach dem Ausschneiden der Bilder ist die Illusion perfekt.

CSS Pizza-Kuchen-Grid
Rate mal? Wir können ein weiteres cooles Grid erhalten, indem wir einfach border-radius und overflow zu unserem Grid oder unseren dreieckigen Formen hinzufügen. 🎉
CSS-Grid aus Puzzleteilen
Dieses Mal werden wir mit der CSS-Eigenschaft mask spielen, um den Bildern das Aussehen von Puzzleteilen zu verleihen.
Wenn Sie mask noch nicht mit CSS-Verläufen verwendet haben, empfehle ich Ihnen dringend diesen anderen Artikel von mir zu diesem Thema, da er Ihnen bei dem Folgenden helfen wird. Warum Verläufe? Weil wir damit die runden Kerben in den Puzzleteilformen erzielen.
Das Einrichten des Grids sollte inzwischen ein Kinderspiel sein, also konzentrieren wir uns stattdessen auf den mask-Teil.
Wie in der obigen Demo gezeigt, benötigen wir zwei Verläufe, um die endgültige Form zu erstellen. Ein Verlauf erzeugt einen Kreis (der grüne Teil) und der andere erzeugt die rechte Kurve, während er den oberen Teil ausfüllt.
--g: 6px; /* controls the gap */
--r: 42px; /* control the circular shapes */
background:
radial-gradient(var(--r) at left 50% bottom var(--r), green 95%, #0000),
radial-gradient(calc(var(--r) + var(--g)) at calc(100% + var(--g)) 50%, #0000 95%, red)
top/100% calc(100% - var(--r)) no-repeat;
Zwei Variablen steuern die Form. Die Variable --g ist nichts anderes als der Grid-Abstand. Wir müssen den Abstand berücksichtigen, um unsere Kreise korrekt zu platzieren, damit sie perfekt überlappen, wenn das gesamte Puzzle zusammengesetzt ist. Die Variable --r steuert die Größe der kreisförmigen Teile der Puzzleform.

Nun nehmen wir dasselbe CSS und aktualisieren einige Werte darin, um die drei anderen Formen zu erstellen
Wir haben die Formen, aber nicht die überlappenden Kanten, die wir brauchen, damit sie zusammenpassen. Jedes Bild ist auf seine Grid-Zelle beschränkt, daher ist es verständlich, warum die Formen im Moment etwas durcheinander sind.

Wir müssen einen Überlauf erzeugen, indem wir die Höhe/Breite der Bilder erhöhen. Aus der obigen Abbildung müssen wir die Höhe des ersten und vierten Bildes erhöhen, während wir die Breite des zweiten und dritten erhöhen. Sie haben wahrscheinlich schon erraten, dass wir sie mithilfe der Variable --r erhöhen müssen.
.gallery > img:is(:nth-child(1),:nth-child(4)) {
width: 100%;
height: calc(100% + var(--r));
}
.gallery > img:is(:nth-child(2),:nth-child(3)) {
height: 100%;
width: calc(100% + var(--r));
}
Wir kommen der Sache näher!
Wir haben die Überlappung erzeugt, aber standardmäßig überlappen sich unsere Bilder entweder rechts (wenn wir die Breite erhöhen) oder unten (wenn wir die Höhe erhöhen). Aber das ist nicht das, was wir für das zweite und vierte Bild wollen. Die Lösung besteht darin, place-self: end auf diese beiden Bilder anzuwenden, und unser vollständiger Code lautet dann wie folgt
Hier ist ein weiteres Beispiel, bei dem ich einen konischen Verlauf anstelle eines radialen Verlaufs verwende. Dies ergibt dreieckige Puzzleteile, während das zugrunde liegende HTML und CSS gleich bleiben.
Ein letztes Mal! Diesmal verwende ich clip-path und da es eine Eigenschaft ist, die wir animieren können, erhalten wir einen coolen Hover-Effekt, indem wir einfach die benutzerdefinierte Eigenschaft aktualisieren, die die Form steuert.
Zusammenfassung
Das war's für diesen ersten Teil! Indem wir die Dinge, die wir bereits über CSS Grid gelernt haben, mit etwas zusätzlicher clip-path und mask Magie kombiniert haben, konnten wir Grid-Layouts mit verschiedenen Arten von Formen erstellen. Und wir haben jedes Mal dasselbe HTML-Markup verwendet! Und das Markup selbst ist nichts weiter als ein Container mit einer Handvoll Bildelementen!
Im zweiten Teil werden wir komplexer aussehende Grids mit schickeren Formen und Hover-Effekten untersuchen.
Ich plane, die Demo von expandierenden Bildfeldern, die wir in diesem anderen Artikel zusammen erstellt haben,
...und sie in zickzackförmige Bildfelder zu verwandeln! Und das ist nur ein Beispiel unter den vielen, die wir im nächsten Artikel entdecken werden.
Das ist so cool! Ich bin immer wieder wirklich beeindruckt von deinen Tutorials, die benutzerdefinierte Eigenschaften und Mathe-Tricks beinhalten.
Ich denke, es wäre hilfreich, wenn du bei diesen Arten von Beiträgen etwas mehr auf die Mathematik eingehen oder Diagramme einfügen würdest. Ich musste die Wabe auf Papier zeichnen, damit die Mathematik klickte, obwohl es rückblickend nur grundlegende Geometrie ist.
Für alle, die sich fragen: Der Radius des Wabenkreises ist
(Größe + Abstand), und wir positionieren sechs Bilder auf seinem Umfang, sodass sie360/60 = 60Grad voneinander entfernt sind. Dann bilden Sie einfach die rechtwinkligen Dreiecke und machen die Mathematik, indem Sie sin(a) oder cos(a) einsetzen, wo nötig.Ich wünschte wirklich, CSS hätte Trig-Funktionen. Dann könnten wir jedem Bild einfach Winkelwerte zuweisen. So bräuchten wir nur zwei Calc-Funktionen: eine für x und eine für y. Da der Winkel je nach Bild variiert, tun das auch die x/y-Koordinaten!
Ich versuche immer, die richtige Balance zwischen mathematischen und nicht-mathematischen Inhalten zu finden. Ich habe Artikel, in denen ich mathematische Formeln im Detail behandle, aber nicht immer, um die Artikel nicht langweilig zu machen, besonders da nicht jeder viel Zeit mit Mathematik verbringen möchte.
Da Sie den mathematischen Teil mögen, hier ist eine weitere Implementierung, bei der Sie keine sin()/cos()-Funktionen benötigen, aber diesmal geben Sie die Winkel so an, wie Sie möchten ;)
Ich überlasse Ihnen die Logik hinter dem Code :)
Danke fürs Teilen.
Diese Demos sind raffiniert.
Wie würden Sie eine Blumenform angehen, wie auf diesem Bild? Insbesondere in Bezug auf eine unterschiedliche Anzahl von Blättern?
Könnte die Blattform in CSS gemacht werden, oder wäre es besser, eine SVG-Lösung anzustreben?
Danke für jeden Hinweis.
Das ist großartig
Wie immer erstaunliche Artikel...
Schöne Demos
Chrome unter Windows hat Probleme mit der Skalierungsanimation, und ich habe zufällige Überstrahlungen an den Bildrändern, ähnlich dem Beispiel in diesem SO-Post: https://stackoverflow.com/questions/67736210/svg-mask-is-bleeding-on-canvas-edges
Etwas mit Antialiasing, wenn es sich bewegt. Könnte ein provisorischer Fix mit einem Elternelement zur Abdeckung der Ränder sein oder einfach nur ein Warten auf einen Chrome-Fix!
Du bist ein Guru. Danke. Ich freue mich auf das letzte, nicht erklärte Beispiel.
Es wäre sehr cool, es mit
shape-outsidezum Laufen zu bringen https://developer.mozilla.org/en-US/docs/Web/CSS/shape-outside, aber ich glaube, das ist nur für Texte, oder?Wie bei Graeme sehe ich auf Firefox Linux Kantenlinien auf den animierten Bildern (auch bevor sie animiert werden), und es scheint, dass es auch ein Problem auf Chrome mobile gibt.
https://stackoverflow.com/questions/51542919/clip-path-on-chrome-leaves-a-strange-line-on-the-edge
Aber das schmälert nicht den Großteil des Artikels, der fantastisch ist. Ich gehe jetzt zu Teil 2.
Dein Tutorial hat mir sehr gefallen!!! Ich lerne viel und werde dem nächsten sehr aufmerksam folgen.
Vielen Dank, dass Sie an diejenigen denken, die gerade erst anfangen und Mathematik nicht immer so mögen.
Herzliche Grüße!!!
Daniel
Hey Mann, du hast einfach zu viel Spaß! Wow!
Ich habe diese Art von Code noch nie gesehen, und es ist lustig, ich dachte gerade an Mathe und Code, und hier zeigst du Bilder in Rauten! Was!!?? Ja, Rauten. Absolut coole Sache. Es wird einen Moment dauern, bis mein kleines Gehirn das alles begreift, aber Mann, du hast einfach zu viel Spaß dabei. Gut gemacht.