Erstellen Sie ansprechende Bildeffekte mit CSS-Verläufen und Seitenverhältnis

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ Ein klassisches Problem in CSS ist die Beibehaltung des Seitenverhältnisses von Bildern über verwandte Komponenten hinweg, wie z. B. Karten. Die neu unterstützte aspect-ratio in Kombination mit object-fit schafft Abhilfe für dieses Problem der Vergangenheit! Lassen Sie uns lernen, diese Eigenschaften zu verwenden, zusätzlich zum Erstellen eines ansprechenden Bildverlaufseffekts für zusätzliches Flair.

Als Vorbereitung auf unsere zukünftigen Bildeffekte richten wir eine Kartenkomponente ein, die oben ein großes Bild enthält, gefolgt von einer Überschrift und einer Beschreibung. Das häufige Problem bei diesem Setup ist, dass wir möglicherweise nicht immer die perfekte Kontrolle darüber haben, was das Bild ist, und was für unser Layout noch wichtiger ist, welche Abmessungen es hat. Und obwohl dies durch vorzeitiges Zuschneiden behoben werden kann, können wir immer noch auf Probleme aufgrund von Containern mit ansprechender Größe stoßen. Die Folge sind ungleichmäßige Positionen des Karteninhalts, was beim Vorlegen einer Kartenreihe besonders auffällt.

Eine andere frühere Lösung neben dem Zuschneiden könnte darin bestanden haben, von einem Inline- img zu einem leeren div zu wechseln, das nur existierte, um das Bild über background-image . Ich habe diese Lösung in der Vergangenheit oft selbst implementiert. Ein Vorteil ist die Verwendung eines älteren Tricks für das Seitenverhältnis, der ein Element mit der Höhe Null verwendet und einen Wert für die padding-bottom festlegt. Das Festlegen eines Füllwerts in Prozent führt zu einem berechneten Endwert, der relativ zur Breite des Elements ist. Möglicherweise haben Sie diese Idee auch verwendet, um ein 16:9-Verhältnis für Videoeinbettungen beizubehalten. In diesem Fall wird der Auffüllwert mit der Formel ermittelt: 9/16 = 0.5625 * 100% = 56.26% . Aber wir werden zwei moderne CSS-Eigenschaften untersuchen , die keine zusätzliche Mathematik erfordern, uns mehr Flexibilität geben und es auch ermöglichen, die bereitgestellte Semantik beizubehalten, indem ein echtes img anstelle eines leeren div verwendet wird.

Lassen Sie uns zunächst die HTML-Semantik definieren, einschließlich der Verwendung einer ungeordneten Liste als Container der Karten:

 <ul class="card-wrapper"> <li class="card"> <img src="" alt=""> <h3>A Super Wonderful Headline</h3> <p>Lorem ipsum sit dolor amit</p> </li> <!-- additional cards --> </ul>

Als Nächstes erstellen wir einen minimalen Satz von Basisstilen für die .card Komponente. Wir werden einige grundlegende visuelle Stile für die Karte selbst festlegen, eine schnelle Aktualisierung der erwarteten h3 -Überschrift und dann grundlegende Stile, um mit der Gestaltung des Kartenbilds zu beginnen.

 .card { background-color: #fff; border-radius: 0.5rem; box-shadow: 0.05rem 0.1rem 0.3rem -0.03rem rgba(0, 0, 0, 0.45); padding-bottom: 1rem; } .card > :last-child { margin-bottom: 0; } .card h3 { margin-top: 1rem; font-size: 1.25rem; } img { border-radius: 0.5rem 0.5rem 0 0; width: 100%; } img ~ * { margin-left: 1rem; margin-right: 1rem; }

Die letzte Regel verwendet den allgemeinen Geschwisterkombinator , um jedem Element, das auf das Bild folgt, einen horizontalen Rand img , da wir möchten, dass das Bild selbst mit den Seiten der Karte bündig ist.

Und unser bisheriger Fortschritt führt uns zu folgendem Kartenauftritt:

Eine Karte mit den zuvor beschriebenen Basisstilen und einem Bild von Unsplash mit einem Dessert auf einem kleinen Teller neben einem heißen Getränk in einem Becher
Eine Karte mit den zuvor beschriebenen Basisstilen und einem Bild von Unsplash mit einem Dessert auf einem kleinen Teller neben einem heißen Getränk in einem Becher. (Große Vorschau)

Schließlich erstellen wir die .card-wrapper Stile für ein schnell ansprechendes Layout mit CSS-Raster. Dadurch werden auch die Standardlistenstile entfernt.

 .card-wrapper { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(30ch, 1fr)); grid-gap: 1.5rem; }

Hinweis : Wenn Ihnen diese Rastertechnik nicht vertraut ist, lesen Sie die Erklärung in meinem Tutorial über moderne Lösungen für das 12-Spalten-Raster.

Wenn dies angewendet wird und alle Karten ein Bild mit einem gültigen Quellpfad enthalten, geben uns unsere .card-wrapper Stile das folgende Layout:

Aufgrund der angewendeten Layoutstile für die Kartenverpackung werden drei Karten in einer Reihe angezeigt. Jede Karte hat ein einzigartiges Bild mit unterschiedlichen natürlichen Seitenverhältnissen, wobei die letzte Karte ein vertikal ausgerichtetes Bild hat, das mehr als doppelt so hoch ist wie die anderen Kartenbilder
Aufgrund der angewendeten Layoutstile für die Kartenverpackung werden drei Karten in einer Reihe angezeigt. Jede Karte hat ein einzigartiges Bild mit unterschiedlichen natürlichen Seitenverhältnissen, wobei die letzte Karte ein vertikal ausgerichtetes Bild hat, das mehr als doppelt so hoch ist wie die anderen Kartenbilder. (Große Vorschau)

Wie im Vorschaubild gezeigt, reichen diese Grundlinienstile nicht aus, um die Bilder aufgrund ihrer unterschiedlichen natürlichen Abmessungen richtig einzuschließen. Wir brauchen eine Methode, um diese Bilder einheitlich und konsistent einzuschränken.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

Aktivieren Sie einheitliche Bildgrößen mit object-fit

Wie bereits erwähnt, haben Sie in diesem Szenario möglicherweise zuvor ein Update vorgenommen, um die Bilder zu ändern, die stattdessen über background-image hinzugefügt werden sollen, und background-size: cover verwendet, um die Größe des Bilds ansprechend zu handhaben. Oder Sie haben vielleicht versucht, das Zuschneiden vorzeitig zu erzwingen (immer noch ein lohnendes Ziel, da jede Reduzierung der Bildgröße die Leistung verbessert!).

Jetzt haben wir die Eigenschaft object-fit zur Verfügung, die es einem img -Tag ermöglicht, als Container für das Bild zu fungieren. Und es kommt auch mit einem cover , der zu einem ähnlichen Effekt wie die Hintergrundbildlösung führt, aber mit dem Bonus , die Semantik eines Inline-Bildes beizubehalten. Wenden wir es an und sehen, wie es funktioniert.

Wir müssen es mit einer height koppeln, um zusätzliche Hinweise zum Verhalten des Bildcontainers zu erhalten (denken Sie daran, dass wir bereits width: 100% hinzugefügt hatten). Und wir werden die Funktion max() verwenden, um entweder 10rem oder 30vh je nachdem, was in einem bestimmten Kontext größer ist, wodurch verhindert wird, dass die Bildhöhe bei kleineren Ansichtsfenstern oder wenn der Benutzer einen großen Zoom eingestellt hat, zu stark schrumpft.

 img { /* ...existing styles */ object-fit: cover; height: max(10rem, 30vh); }

Bonustipp zur Barrierefreiheit : Sie sollten Ihre Layouts immer mit 200 % und 400 % Zoom auf dem Desktop testen. Obwohl es derzeit keine zoom -Medienabfrage gibt, können Funktionen wie max() helfen, Layoutprobleme zu lösen. Ein weiterer Kontext, in dem diese Technik nützlich ist, ist der Abstand zwischen Elementen.

Mit diesem Update haben wir die Dinge definitiv verbessert, und das visuelle Ergebnis ist so, als ob wir die ältere Hintergrundbildtechnik verwenden würden:

Die Drei-Karten-Bilder scheinen nun eine einheitliche Höhe zu haben und die Bildinhalte sind innerhalb des Bildes zentriert, als wäre es ein Container
Die Drei-Karten-Bilder scheinen nun eine einheitliche Höhe zu haben und die Bildinhalte sind innerhalb des Bildes zentriert, als wäre es ein Container. (Große Vorschau)

Responsive konsistente Bildgröße mit aspect-ratio

Wenn Sie die object-fit allein verwenden, besteht ein Nachteil darin, dass wir noch einige Bemaßungshinweise festlegen müssen.

Eine kommende Eigenschaft (derzeit in Chromium aspect-ratio wird unsere Fähigkeit zur konsistenten Größenanpassung von Bildern verbessern.

Mit dieser Eigenschaft können wir ein Verhältnis definieren , um die Größe des Bildes zu ändern, anstatt explizite Abmessungen festzulegen. Wir werden es weiterhin in Kombination mit object-fit verwenden, um sicherzustellen, dass sich diese Abmessungen nur auf das Bild als Container auswirken, da das Bild sonst verzerrt erscheinen könnte.

Hier ist unsere vollständig aktualisierte Bildregel:

 img { border-radius: 0.5rem 0.5rem 0 0; width: 100%; object-fit: cover; aspect-ratio: 4/3; }

Wir beginnen mit einem Bildverhältnis von 43 für unseren Kartenkontext, aber Sie können ein beliebiges Verhältnis wählen. Zum Beispiel 11 für ein Quadrat oder 169 für standardmäßige Videoeinbettungen.

Hier sind die aktualisierten Karten, obwohl es in diesem speziellen Fall wahrscheinlich schwierig sein wird, den visuellen Unterschied zu erkennen, da das Seitenverhältnis zufällig genau dem Erscheinungsbild entspricht, das wir erreicht haben, indem wir die height nur für die object-fit eingestellt haben.

Die Drei-Karten-Bilder haben identische Breiten- und Höhenabmessungen, die sich geringfügig von der vorherigen Objektanpassungslösung unterscheiden
Die Drei-Karten-Bilder haben identische Breiten- und Höhenabmessungen, die sich geringfügig von der vorherigen Objektanpassungslösung unterscheiden. (Große Vorschau)

Das Festlegen eines „Seitenverhältnisses“ führt dazu, dass das Verhältnis beibehalten wird, wenn die Elemente wachsen oder schrumpfen, wohingegen wenn nur „Objektanpassung“ und „Höhe“ eingestellt werden, das Bildverhältnis ständig im Fluss ist, wenn sich die Behälterabmessungen ändern.

Responsive Effekte mit CSS-Verläufen und -Funktionen hinzufügen

OK, jetzt, da wir wissen, wie man Bilder mit einheitlicher Größe einrichtet, lassen Sie uns etwas Spaß mit ihnen haben, indem Sie einen Verlaufseffekt hinzufügen!

Unser Ziel bei diesem Effekt ist es, den Eindruck zu erwecken, als würde das Bild in den Karteninhalt übergehen. Sie könnten versucht sein, das Bild in einen eigenen Container zu packen, um den Farbverlauf hinzuzufügen, aber dank der Arbeit, die wir bereits an der Bildgrößenanpassung geleistet haben, können wir herausfinden, wie dies auf der Haupt- .card sicher durchgeführt werden kann.

Der erste Schritt besteht darin , einen Farbverlauf zu definieren . Wir werden eine benutzerdefinierte CSS-Eigenschaft verwenden, um die Verlaufsfarben hinzuzufügen, damit der Verlaufseffekt einfach ausgetauscht werden kann, beginnend mit Blau bis Pink. Die letzte Farbe im Farbverlauf ist immer Weiß, um den Übergang in den Hintergrund des Karteninhalts beizubehalten und den „gefederten“ Rand zu erzeugen.

 .card { --card-gradient: #5E9AD9, #E271AD; background-image: linear-gradient( var(--card-gradient), white max(9.5rem, 27vh) ); /* ...existing styles */ }

Aber warten Sie – ist das eine CSS max() -Funktion? In einem Gefälle? Ja, es ist möglich, und es ist die Magie, die diesen Farbverlauf reaktionsschnell macht!

Wenn ich jedoch einen Screenshot hinzufügen würde, würden wir noch nicht sehen, dass der Farbverlauf Auswirkungen auf das Bild hat. Dafür müssen wir die mix-blend-mode Eigenschaft einbringen, und in diesem Szenario verwenden wir den overlay -Wert:

 img { /* ...existing styles */ mix-blend-mode: overlay; }

Die mix-blend-mode Eigenschaft ähnelt dem Anwenden der Ebenenüberblendungsstile, die in Fotobearbeitungssoftware wie Photoshop verfügbar sind. Und der overlay bewirkt, dass sich die mittleren Töne im Bild mit dem dahinter liegenden Farbverlauf vermischen , was zu folgendem Ergebnis führt:

Jedes Kartenbild hat einen Verlaufsmischeffekt, der mit einem hellen Blau oben beginnt, das zu einem rötlichen Rosa übergeht und dann endet, indem es vor dem Rest des Kartentextinhalts in ein Weiß übergeht
Jedes Kartenbild hat einen Verlaufsmischeffekt, der mit einem hellen Blau oben beginnt, das zu einem rötlichen Rosa übergeht und dann endet, indem es vor dem Rest des Kartentextinhalts in ein Weiß übergeht. (Große Vorschau)

An diesem Punkt verlassen wir uns allein auf den aspect-ratio , um die Größe des Bildes zu ändern. Und wenn wir die Größe des Containers ändern und das Kartenlayout umfließen lassen, führt die sich ändernde Bildhöhe zu Inkonsistenzen dort, wo der Farbverlauf zu Weiß verblasst.

Daher fügen wir auch eine max-height Eigenschaft hinzu, die ebenfalls die max() Funktion verwendet und Werte enthält, die geringfügig größer sind als die im Farbverlauf. Das resultierende Verhalten ist, dass der Farbverlauf (fast immer) korrekt am unteren Rand des Bildes ausgerichtet wird.

 img { /* ...existing styles */ max-height: max(10rem, 30vh); }

Es ist wichtig zu beachten, dass das Hinzufügen einer „Max-Höhe“ das Verhalten des „Seitenverhältnisses“ verändert. Anstatt immer das exakte Verhältnis zu verwenden, wird es aufgrund der neuen zusätzlichen Beschränkung der „Max-Höhe“ nur dann verwendet, wenn genügend Platz zugeteilt ist.

Das aspect-ratio stellt jedoch weiterhin sicher, dass die Größe der Bilder konsistent geändert wird, da dies der Vorteil gegenüber der reinen object-fit war. Versuchen Sie, das aspect-ratio Demo zu kommentieren, um den Unterschied zu sehen, den es bei den Containergrößen macht.

Da unser ursprüngliches Ziel darin bestand, konsistent responsive Bildabmessungen zu ermöglichen, haben wir immer noch ins Schwarze getroffen. Für Ihren eigenen Anwendungsfall müssen Sie möglicherweise mit den Verhältnis- und Höhenwerten herumspielen, um den gewünschten Effekt zu erzielen.

Alternative: mix-blend-mode und Hinzufügen eines Filters

Die Verwendung von overlay als mix-blend-mode Wert war die beste Wahl für den Fade-to-White-Effekt, nach dem wir gesucht haben, aber lassen Sie uns eine alternative Option für einen dramatischeren Effekt ausprobieren.

Wir werden unsere Lösung aktualisieren, um eine benutzerdefinierte CSS-Eigenschaft für den mix-blend-mode Wert hinzuzufügen und auch die Farbwerte für den Farbverlauf zu aktualisieren:

 .card { --card-gradient: tomato, orange; --card-blend-mode: multiply; } img { /* ...existing styles */ mix-blend-mode: var(--card-blend-mode); }

Der multiply hat einen verdunkelnden Effekt auf Mitteltöne, behält aber Weiß und Schwarz bei, was zu folgendem Erscheinungsbild führt:

Jedes Kartenbild hat einen starken orangefarbenen Farbton aus dem neuen Farbverlauf, der von Rot-Orange bis zu reinem Orange reicht. Weiße Bereiche sind immer noch weiß und schwarze Bereiche sind immer noch schwarz
Jedes Kartenbild hat einen starken orangefarbenen Farbton aus dem neuen Farbverlauf, der von Rot-Orange bis zu reinem Orange reicht. Weiße Bereiche sind immer noch weiß und schwarze Bereiche sind immer noch schwarz. (Große Vorschau)

Obwohl wir die Überblendung verloren haben und jetzt eine harte Kante am unteren Rand des Bildes haben, ist der weiße Teil unseres Farbverlaufs immer noch wichtig, um sicherzustellen, dass der Farbverlauf vor dem Karteninhalt endet.

Eine zusätzliche Modifikation , die wir hinzufügen können, ist die Verwendung von filter und insbesondere die Verwendung der grayscale() Funktion, um die Bildfarben zu entfernen und damit den Farbverlauf als einzige Quelle für die Bildfärbung zu verwenden.

 img { /* ...existing styles */ filter: grayscale(100); }

Die Verwendung des grayscale(100) führt zu einer vollständigen Entfernung der natürlichen Farben des Bilds und einer Umwandlung in Schwarzweiß. Hier ist das Update zum Vergleich mit dem vorherigen Screenshot seines Effekts bei Verwendung unseres orangefarbenen Farbverlaufs mit multiply :

Jetzt hat jedes Kartenbild immer noch den orangefarbenen Verlauf, aber alle anderen Farben werden entfernt und durch Grauschattierungen ersetzt
Jetzt hat jedes Kartenbild immer noch den orangefarbenen Verlauf, aber alle anderen Farben werden entfernt und durch Grauschattierungen ersetzt. (Große Vorschau)

Verwenden Sie aspect-ratio als progressive Verbesserung

Wie bereits erwähnt, wird das aspect-ratio Browsern (Chrome und Edge) unterstützt. Alle Browser unterstützen jedoch die object-fit und das führt zusammen mit unseren height zu einem weniger idealen, aber immer noch akzeptablen Ergebnis, das hier für Safari zu sehen ist:

Die Kartenbildhöhe ist begrenzt, aber jede Karte hat eine etwas andere realisierte Höhe
Die Kartenbildhöhe ist begrenzt, aber jede Karte hat eine etwas andere realisierte Höhe. (Große Vorschau)

Ohne die Funktion des aspect-ratio ist das Ergebnis hier, dass die Bildhöhe letztendlich begrenzt wird, aber die natürlichen Abmessungen jedes Bildes führen immer noch zu einer gewissen Abweichung zwischen den Kartenbildhöhen. Vielleicht möchten Sie stattdessen zum Hinzufügen einer max-height wechseln oder die Funktion max() erneut verwenden, um eine max-height für unterschiedliche Kartengrößen reaktionsfähiger zu machen.

Erweitern der Verlaufseffekte

Da wir die Stopps der Verlaufsfarbe als benutzerdefinierte CSS-Eigenschaft definiert haben, haben wir direkten Zugriff, um sie in verschiedenen Kontexten zu ändern. Beispielsweise können wir den Farbverlauf ändern, um eine der Farben stärker hervorzuheben, wenn die Karte mit der Maus bewegt wird oder eines ihrer untergeordneten Elemente im Fokus ist.

Zuerst aktualisieren wir jede Karte h3 so, dass sie einen Link enthält, wie zum Beispiel:

 <h3><a href="">A Super Wonderful Headline</a></h3>

Dann können wir einen unserer neuesten verfügbaren Selektoren – :focus-within – verwenden, um den Kartengradienten zu ändern, wenn der Link im Fokus ist. Für eine zusätzliche Abdeckung möglicher Interaktionen koppeln wir dies mit :hover . Und wir werden unsere max() Idee wiederverwenden, um eine einzelne Farbe zuzuweisen, die die Abdeckung des Bildteils der Karte übernimmt. Der Nachteil dieses speziellen Effekts ist, dass Verlaufsstopps und Farbänderungen nicht zuverlässig animierbar sind – aber dank CSS Houdini werden sie es bald sein.

Um die Farbe zu aktualisieren und den neuen Farbstopp hinzuzufügen, müssen wir nur den Wert von --card-gradient innerhalb dieser neuen Regel neu zuweisen:

 .card:focus-within, .card:hover { --card-gradient: #24a9d5 max(8.5rem, 20vh); }

Unsere max() Werte sind kleiner als die ursprünglich für white verwendeten Werte, um den gefiederten Rand beizubehalten. Wenn wir die gleichen Werte verwenden würden, würde es auf das white treffen und eine deutliche Linealtrennung erzeugen.

Bei der Erstellung dieser Demo habe ich ursprünglich einen Effekt ausprobiert, der eine transform mit scale für einen Zoom-in-Effekt verwendete. Ich stellte jedoch fest, dass der Browser aufgrund des angewendeten mix-blend-mode das Bild nicht konsequent neu zeichnete, was ein unangenehmes Flackern verursachte. Es wird immer Kompromisse geben, wenn Sie den Browser auffordern, Nur-CSS-Effekte und -Animationen auszuführen, und obwohl es sehr cool ist, was wir tun können , ist es immer am besten, die Auswirkungen Ihrer Effekte auf die Leistung zu überprüfen .

Viel Spaß beim Experimentieren!

Modernes CSS hat uns einige großartige Tools zum Aktualisieren unserer Webdesign-Toolkits zur Verfügung gestellt, wobei das aspect-ratio die neueste Ergänzung ist. Also machen Sie weiter und experimentieren Sie mit object-fit , aspect-ratio und dem Hinzufügen von Funktionen wie max() zu Ihren Farbverläufen für einige lustige reaktionsschnelle Effekte! Stellen Sie nur sicher, dass Sie die Dinge browserübergreifend (vorerst!) und über verschiedene Darstellungsbereiche und Containergrößen hinweg überprüfen.

Hier ist der CodePen mit den Funktionen und Effekten, die wir heute getestet haben:

Siehe Stift [Responsive Bildeffekte mit CSS-Verläufen und Seitenverhältnis](https://codepen.io/smashingmag/pen/WNoERXo) von Stephanie Eckles.

Sehen Sie sich die Pen Responsive Image Effects mit CSS-Verläufen und Seitenverhältnis von Stephanie Eckles an.

Suchen Sie mehr? Schauen Sie sich unbedingt unseren CSS-Leitfaden hier auf Smashing → an