Erstellen Sie ansprechende Bildeffekte mit CSS-Verläufen und Seitenverhältnis
Veröffentlicht: 2022-03-10aspect-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:
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:
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.
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:
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 4 ⁄ 3 für unseren Kartenkontext, aber Sie können ein beliebiges Verhältnis wählen. Zum Beispiel 1 ⁄ 1 für ein Quadrat oder 16 ⁄ 9 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.
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:
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:
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
:
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:
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:
Suchen Sie mehr? Schauen Sie sich unbedingt unseren CSS-Leitfaden hier auf Smashing → an