Warum sollten wir Schatten auf SVG anwenden müssen?
- Schatten sind ein gängiges Designmerkmal, das Elementen wie Icons helfen kann, hervorzustechen. Sie können dauerhaft sein oder in verschiedenen Zuständen (z. B.
:hover,:focusoder:active) angewendet werden, um dem Benutzer Interaktion anzuzeigen. - Schatten gibt es im wirklichen Leben, daher können sie auf Bildschirmen verwendet werden, um Ihren Elementen Leben einzuhauchen und einen Hauch von Realismus zu einem Design zu verleihen.
Da wir Listen erstellen, gibt es zwei Hauptmethoden, mit denen wir Schatten auf ein SVG anwenden können
- Verwenden der CSS-Eigenschaft
filter() - Verwenden eines SVG
<filter>
Ja, beides beinhaltet Filter! Und ja, sowohl CSS als auch SVG haben ihre eigenen Arten von Filtern. Aber es gibt auch einige Überschneidungen zwischen ihnen. Zum Beispiel kann ein CSS filter sich auf ein SVG <filter> beziehen; das heißt, wenn wir mit einem Inline-SVG statt z. B. einem als Hintergrundbild in CSS verwendeten SVG arbeiten.
Was Sie nicht verwenden können: die CSS-Eigenschaft box-shadow. Diese wird häufig für Schatten verwendet, folgt aber dem rechteckigen Außenrand von Elementen, nicht den Kanten von SVG-Elementen, wie wir es möchten. Hier hat Michelle Barker eine klare Erklärung

Wenn Sie jedoch ein SVG-Icon-Font verwenden, gibt es immer text-shadow. Das funktioniert tatsächlich. Aber konzentrieren wir uns auf die ersten beiden, da sie mit der Mehrheit der Anwendungsfälle übereinstimmen.
Schatten mit CSS-Filtern
Der Trick beim direkten Anwenden eines Schattens auf SVG über CSS-Filter ist die Funktion drop-shadow()
svg {
filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));
}
Dies wendet einen Schatten an, der bei 3px horizontal, 5px nach unten, mit 2px Unschärfe beginnt und 40% schwarz ist. Hier sind einige Beispiele dafür
Diese Daten zur Browserunterstützung stammen von Caniuse, wo weitere Details zu finden sind. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 18* | 35 | Nein | 79 | 6* |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 4.4* | 6.0-6.1* |
Aufrufen eines SVG-Filters innerhalb eines CSS-Filters
Nehmen wir an, wir haben einen SVG-Filter im HTML
<svg height="0" width="0">
<filter id='shadow' color-interpolation-filters="sRGB">
<feDropShadow dx="2" dy="2" stdDeviation="3" flood-opacity="0.5"/>
</filter>
</svg>
Wir können einen CSS-Filter verwenden, um diesen SVG-Filter anhand der ID aufzurufen, anstatt der zuvor gezeigten Werte
svg {
filter: url(#shadow);
}
Nun wird dieser Filter aus dem HTML übernommen und im CSS referenziert, was ihn anwendet.
Verwenden von SVG-Filter-Primitiven
Sie fragen sich vielleicht, wie wir diesen SVG-<filter> zum Laufen gebracht haben. Um einen Drop-Schatten mit einem SVG-Filter zu erstellen, verwenden wir ein Filter-Primitiv. Ein Filter-Primitiv in SVG ist ein Element, das eine Art Bild oder Grafik als Eingabe nimmt und dieses Bild oder diese Grafik ausgibt, wenn es aufgerufen wird. Sie funktionieren so ähnlich wie Filter in einer Grafikbearbeitungsanwendung, aber im Code und können nur innerhalb eines SVG-<filter>-Elements verwendet werden.
Es gibt viele verschiedene Filter-Primitive in SVG. Das, was wir verwenden, ist <feDropShadow>. Ich überlasse es Ihnen zu erraten, was es tut, nur anhand des Namens.
Also, ähnlich wie wir etwas hatten, das dies mit einem CSS-Filter getan hat
svg {
filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));
}
…können wir dasselbe mit dem <feDropShadow> SVG-Filter-Primitiv erreichen. Es gibt drei Schlüsselattribute, die es wert sind, erwähnt zu werden, da sie das Aussehen des Drop-Schattens definieren helfen
dx— Dies verschiebt die Position des Schattens entlang der x-Achse.dy— Dies verschiebt die Position des Schattens entlang der y-Achse.stdDeviation— Dies definiert die Standardabweichung für den Unschärfevorgang des Drop-Schattens. Es gibt andere Attribute, die wir verwenden können, wie z. B.flood-colorzum Festlegen der Farbe des Drop-Schattens undflood-opacityzum Festlegen der Opazität des Drop-Schattens.
Dieses Beispiel enthält drei <filter>-Elemente, jedes mit seinem eigenen <feDropShadow>-Filter-Primitiv.
Verwenden von SVG-Filtern
SVG-Filter sind sehr mächtig. Wir haben gerade <feDropShadow> behandelt, was natürlich sehr nützlich ist, aber es gibt noch viel mehr, was sie können (einschließlich Photoshop-ähnlicher Effekte), und die Teilmenge dessen, was wir nur für Schatten bekommen, ist umfangreich. Schauen wir uns einige an, wie farbige Schatten und Innen-Schatten.
Nehmen wir den SVG-Markup für das Twitter-Logo als Beispiel
<svg class="svg-icon" viewBox="0 0 20 20">
<path fill="#4691f6" d="M18.258,3.266c-0.693,0.405-1.46,0.698-2.277,0.857c-0.653-0.686-1.586-1.115-2.618-1.115c-1.98,0-3.586,1.581-3.586,3.53c0,0.276,0.031,0.545,0.092,0.805C6.888,7.195,4.245,5.79,2.476,3.654C2.167,4.176,1.99,4.781,1.99,5.429c0,1.224,0.633,2.305,1.596,2.938C2.999,8.349,2.445,8.19,1.961,7.925C1.96,7.94,1.96,7.954,1.96,7.97c0,1.71,1.237,3.138,2.877,3.462c-0.301,0.08-0.617,0.123-0.945,0.123c-0.23,0-0.456-0.021-0.674-0.062c0.456,1.402,1.781,2.422,3.35,2.451c-1.228,0.947-2.773,1.512-4.454,1.512c-0.291,0-0.575-0.016-0.855-0.049c1.588,1,3.473,1.586,5.498,1.586c6.598,0,10.205-5.379,10.205-10.045c0-0.153-0.003-0.305-0.01-0.456c0.7-0.499,1.308-1.12,1.789-1.827c-0.644,0.28-1.334,0.469-2.06,0.555C17.422,4.782,17.99,4.091,18.258,3.266" ></path>
</svg>
Wir benötigen ein <filter>-Element, um diese Effekte zu erzielen. Dies muss sich innerhalb eines <svg>-Elements im HTML befinden. Ein <filter>-Element wird niemals direkt im Browser gerendert — es dient nur als etwas, auf das über das filter-Attribut in SVG oder die url()-Funktion in CSS verwiesen werden kann.
Hier ist die Syntax, die einen SVG-Filter zeigt und ihn auf ein Quellbild anwendet
<svg width="300" height="300" viewBox="0 0 300 300">
<filter id="myfilters">
<!-- All filter effects/primitives go in here -->
</filter>
<g filter="url(#myfilters)">
<!-- Filter applies to everything in this group -->
<path fill="..." d="..." ></path>
</g>
</svg>
Das filter-Element soll Filter-Primitive als Kinder enthalten. Es ist ein Container für eine Reihe von Filteroperationen, die kombiniert werden, um einen Filtereffekt zu erzeugen.
Diese Filter-Primitive führen eine einzelne grundlegende grafische Operation (z. B. Weichzeichnen, Verschieben, Füllen, Kombinieren oder Verzerren) auf einer oder mehreren Eingaben aus. Sie sind wie Bausteine, wobei jeder SVG-Filter in Verbindung mit anderen verwendet werden kann, um einen Effekt zu erzeugen. <feGaussianBlur> ist ein beliebtes Filter-Primitiv, das verwendet wird, um einen Weichzeichnungseffekt hinzuzufügen.
Nehmen wir an, wir definieren den folgenden SVG-Filter mit <feGaussianBlur>
<svg version="1.1" width="0" height="0">
<filter id="gaussian-blur">
<feGaussianBlur stdDeviation="1 0" />
</filter>
</svg>
Wenn dieser Filter auf ein Element angewendet wird, erzeugt er einen Gaußschen Weichzeichner, der das Element mit einem Radius von 1px auf der x-Achse weichzeichnet, aber keine Weichzeichnung auf der y-Achse. Hier ist das Ergebnis, mit und ohne den Effekt
Es ist möglich, mehrere Primitive innerhalb eines einzigen Filters zu verwenden. Dies erzeugt interessante Effekte, aber Sie müssen die verschiedenen Primitive voneinander abhängig machen. Bence Szabó hat eine verdammt coole Sammlung von Mustern, die er auf diese Weise erstellt hat.
Beim Kombinieren mehrerer Filter-Primitive verwendet das erste Primitiv die Originalgrafik (SourceGraphic) als seine grafische Eingabe. Jedes nachfolgende Primitiv verwendet das Ergebnis des vorherigen Filtereffekts als seine Eingabe. Und so weiter. Aber wir können mit den Attributen in, in2 und result auf den Primitiv-Elementen etwas Flexibilität erzielen. Steven Bradley hat eine ausgezeichnete Abhandlung über Filter-Primitive, die aus dem Jahr 2016 stammt, aber heute noch Gültigkeit hat.
Es gibt 17 Primitive, die wir heute verwenden können
<feGaussianBlur><feDropShadow><feMorphology><feDisplacementMap><feBlend><feColorMatrix><feConvolveMatrix><feComponentTransfer><feSpecularLighting><feDiffuseLighting><feFlood><feTurbulence><feImage><feTile><feOffset><feComposite><feMerge>
Beachten Sie das fe-Präfix bei allen. Das steht für *filter effect*. Das Verstehen von SVG-Filtern ist herausfordernd. Ein Effekt wie ein Innen-Schatten erfordert eine ausführliche Syntax, die ohne ein tiefes Verständnis von Mathematik und Farbtheorie schwer zu erfassen ist. (Rob O’Learys „Getting Deep Into Shadows“ ist ein guter Ausgangspunkt.)
Anstatt uns in dieses Kaninchenloch zu begeben, werden wir mit einigen vorgefertigten Filtern arbeiten. Glücklicherweise gibt es viele gebrauchsfertige SVG-Filter.
Innen-Schatten
Um einen Filtereffekt auf das Twitter-Logo anzuwenden, müssen wir ihn in unserem „SVG-Quellendokument“ mit einer eindeutigen ID deklarieren, auf die in unserem <filter>-Tag verwiesen werden kann.
<filter id='inset-shadow'>
<!-- Shadow offset -->
<feOffset
dx='0'
dy='0'
/>
<!-- Shadow blur -->
<feGaussianBlur
stdDeviation='1'
result='offset-blur'
/>
<!-- Invert drop shadow to make an inset shadow -->
<feComposite
operator='out'
in='SourceGraphic'
in2='offset-blur'
result='inverse'
/>
<!-- Cut color inside shadow -->
<feFlood
flood-color='black'
flood-opacity='.95'
result='color'
/>
<feComposite
operator='in'
in='color'
in2='inverse'
result='shadow'
/>
<!-- Placing shadow over element -->
<feComposite
operator='over'
in='shadow'
in2='SourceGraphic'
/>
</filter>
Es gibt vier verschiedene Primitive darin, und jedes führt eine andere Funktion aus. Aber zusammen erreichen sie einen Innen-Schatten.






Nachdem wir diesen Innen-Schatten-Filter erstellt haben, können wir ihn auf unser SVG anwenden. Wir haben bereits gesehen, wie wir ihn über CSS anwenden. Etwas wie
.filtered {
filter: url(#myfilters);
}
/* Or apply only in certain states, like: */
svg:hover, svg:focus {
filter: url(#myfilters);
}
Wir können auch einen SVG-<filter> direkt innerhalb der SVG-Syntax mit dem filter-Attribut anwenden. Das ist wie
<svg>
<!-- Apply a single filter -->
<path d="..." filter="url(#myfilters)" />
<!-- Or apply to a whole group of elements -->
<g filter="url(#myfilters)">
<path d="..." />
<path d="..." />
</g>
</svg>
Weitere Beispiele
Hier sind weitere Schattenbeispiele von Oleg Solomka
Beachten Sie, dass die einfachen Schatten hier wahrscheinlich komplizierter sind als nötig. Zum Beispiel kann ein farbiger Schatten immer noch mit <feDropShadow> wie folgt erstellt werden
<feDropShadow dx="-0.8" dy="-0.8" stdDeviation="0"
flood-color="pink" flood-opacity="0.5"/>
Aber dieser geprägte Effekt ist als Filter ziemlich großartig!
Beachten Sie auch, dass Sie SVG-Filter möglicherweise in SVG-Syntax wie folgt sehen
<svg height="0" width="0" style="position: absolute; margin-left: -100%;">
<defs>
<filter id="my-filters">
<!-- ... -->
</filter>
<symbol id="my-icon">
<!-- ... -->
</symbol>
</defs>
</svg>
In der ersten Zeile dort heißt es: Dieses SVG soll überhaupt nicht gerendert werden – es sind nur Dinge, die wir später verwenden wollen. Das <defs>-Tag sagt etwas Ähnliches: Wir definieren diese Dinge nur zur späteren Verwendung. Auf diese Weise müssen wir uns nicht wiederholen, indem wir Dinge immer und immer wieder schreiben. Wir werden auf den Filter anhand der ID verweisen, und die Symbole ebenfalls, vielleicht so
<svg>
<use xlink:href="#my-icon" />
</svg>
SVG-Filter haben eine breite Unterstützung (sogar in Internet Explorer und Edge!) mit sehr schneller Leistung.
Diese Daten zur Browserunterstützung stammen von Caniuse, wo weitere Details zu finden sind. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 8 | 3 | 10 | 12 | 6 |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 4.4 | 6.0-6.1 |
Zusammenfassung
Ein abschließender Vergleich
- CSS-Filter sind einfacher zu verwenden, aber viel eingeschränkter. Ich glaube nicht, dass es möglich ist, mit der Funktion
drop-shadow()einen Innen-Schatten hinzuzufügen, zum Beispiel. - SVG-Filter sind viel robuster, aber auch viel komplizierter und erfordern, dass das
<filter>irgendwo im HTML vorhanden ist. - Beide haben eine großartige Browserunterstützung und funktionieren gut in allen modernen Browsern, obwohl SVG-Filter (überraschenderweise) die tiefste Browserunterstützung haben.
In diesem Artikel haben wir gesehen, warum und wie man Schatten auf SVG-Icons anwendet, mit Beispielen für jeden. Haben Sie das getan, aber es auf eine andere Weise als die hier gezeigten getan? Haben Sie versucht, einen Schatteneffekt zu erzielen, der sich als unmöglich herausstellte? Bitte teilen Sie es mit!
Warum verwenden Sie rgb(0 0 0 / 0.4) anstelle von rbgba(0, 0, 0, .4)?
Danke für die Antwort.
Es ist die neue Syntax für Farben: https://www.w3.org/TR/css-color-4/#rgb-functions
Lassen Sie uns über Leistung sprechen. Es ist unklug, die meisten dieser Effekte in realen Situationen zu verwenden, und es ist extrem gefährlich, sie zu überbeanspruchen. Als ich zum Beispiel durch den Artikel auf meinem (High-End-)Telefon gescrollt bin, begann jedes Mal, wenn eine Demo auf meinem Bildschirm erschien, zu ruckeln, während die Grafiken sichtbar waren.
Falls Sie diese mehrmals auf mehreren Icons verwenden müssen, ist das ein No-Go.
Ich würde gerne Daten oder etwas dazu sehen. Ich zweifle nicht, dass es Bedenken gibt, aber wie… die Verwendung eines
filterauf ein paar Icons auf einer Seite, das ist das *eine Ding*, das ein High-End-Handy zum Kriechen bringt? Das ist wild. Hat jemand hier tiefere Details?Danke, aber was ist der Vorteil gegenüber einer viel schlechteren Browserunterstützung (rgb vs rgba)?
Ich bemerkte nur ein leichtes Ruckeln bei dem Herz (❤️)-Beispiel (jedes Mal, wenn ich darüber oder hindurchscrollte) und ich verwende ein Mittelklasse-Handy mit Snapdragon 636, Android 10, und rufe die Seite über Android Webview auf.
Für den Rest der Seite bemerkte ich keine Probleme, aber diese Seite dient nur zur Demonstration verschiedener Möglichkeiten der Schattensetzung und des dafür benötigten CSS, sodass ich bezweifle, dass die Aufzeichnung eines Leistungsprofils für diese Seite jemandem etwas zur Schlussfolgerung liefern wird, außerdem denke ich nicht, dass irgendeine Seite eine derart verrückte Menge an SVG-Icons mit Schatten und Effekten haben könnte.
Obwohl ich sagen muss, dass ich erkenne, dass einige Profilierungen auf alter Hardware das Gegenteil beweisen könnten, aber es sei denn, diese Daten helfen bei der Steigerung der Rendering-Leistung für den Browser, was nicht wirklich in der Verantwortung des Front-End-Entwicklers liegt, geht es nur darum, den besten Weg zu finden, damit die meisten Browser damit keine Probleme haben, nicht am Browser-Engine selbst zu arbeiten, um die Rendering-Leistung zu steigern.
Großartig! Danke dafür.
Übergänge und Animationen kompatibel?
Ja!… Ich glaube, ich habe den Hover-Effekt mit einem kleinen Übergangseffekt implementiert und es hat sehr gut funktioniert!
Ist es möglich, einer Gruppe von SVGs einen Schatten hinzuzufügen, ohne sie zu einer einzigen zu verschmelzen?
Das sieht aus wie das, was ich für mein Neuromorphismus-Projekt brauche. Arbeite an einer Animation, um es so aussehen zu lassen, als ob es sich „erhebt“, aber ich habe gemerkt, dass insbesondere auf PCs, die nicht so gut sind wie meine, CSS-Filter nicht so flüssig aussehen.
Mir ist Internet Explorer egal. Es ist 2022, Leute.