Der folgende Text ist ein Gastbeitrag von Rob Levin. Rob ist Senior UI/UX Developer bei Mavenlink und Co-Autor der Unicorn UI CSS Button Library. Ihr Release 2.0 verwendet ein SVG-Icon-System, und hier teilt er einige Probleme, auf die er unterwegs gestoßen ist, und wie Sie diese erkennen und beheben können. Außerdem stellt Rob ein vollständiges System zur Verfügung, das Sie nutzen können, einschließlich eines funktionierenden Build-Prozesses und einer Demo.
Sie haben gelesen, wie Inline-SVGs besser sind als Schrift-Icons, und sind bereit, den Sprung zu wagen. Sie rufen ein Meeting mit Ihrem Team ein, um den Umstieg auf Inline-SVG-Icons zu besprechen. Ihr Chef ist skeptisch. Er sieht Ihnen in die Augen und sagt: „Können Sie garantieren, dass uns das nicht auf die Füße fällt?“ Sie zögern ein wenig, sammeln aber irgendwie den Mut, um zu bestätigen: „Ja, das ist definitiv der Weg, den wir einschlagen müssen!“
Das war ich vor ein paar Monaten, und hier sind einige „Gotchas“, auf die ich gestoßen bin, mit entsprechenden Workarounds. Ich werde zuerst die Workarounds einzeln untersuchen und dann am Ende ein funktionierendes Beispiel geben.
Bitte beachten Sie, dass dies kein überzeugender Artikel darüber ist, warum Sie Inline-SVG verwenden sollten. Dafür sollten Sie diesen beliebten CSS-Tricks-Artikel lesen, der die Vorteile von Inline-SVG gegenüber Schrift-Icons aufzeigt.
Gotcha Eins: Das Ziel verfehlt
Um Caching mit einer externen SVG-Datei zu erreichen (Sie wollen wirklich nicht ~1,5 KB * 50 Icons auf Ihre Seite werfen, ohne dass sie cachebar sind, oder?!), müssen Sie die svg4everybody-Bibliothek auf Ihrer Seite einbinden. Im Wesentlichen wird dieser Shim UA-Sniffing verwenden, um zu erkennen, ob Sie eine „problematische Version“ von IE oder Android verwenden, die externe Definitionsdateien nicht richtig cacht, und wenn ja, werden alle svg use-Elemente entfernt und durch eingebettete Elemente ersetzt, die die entsprechenden SVG-Definitionsdaten enthalten, die per AJAX abgerufen werden. Am Ende des Tages interessiert uns nur die Tatsache, dass unser ursprüngliches SVG, das vielleicht so aussah
<svg viewBox="0 0 16 16">
<use xlink:href="/path/to/svgdef.svg#your-icon" … ></use>
</svg>
Ersetzt wird durch ein eingebettetes Element, das etwa so aussieht
<svg viewBox="0 0 16 16">
<path> ... </path>
</svg>
CSS: Das Ziel treffen
Abhängig vom Quell-SVG kann die Hierarchie wie folgt aussehen: svg path (wie oben), oder es kann svg g sein, oder möglicherweise eine Kombination aus gruppierten und Pfad-Nachkommen – aber denken Sie daran, dass Sie Ihr CSS benötigen, um die „pollyfilled“ Fälle anzusprechen – das bedeutet, Ihre CSS-Regeln sollten absolut niemals direkt das Element svg > use ansprechen… es wird in IE komplett entfernt!
JavaScript: Das Ziel treffen
Die gleiche Idee gilt für alle JavaScript-Manipulationen am SVG-Klon selbst. Zum Beispiel möchten wir möglicherweise Icons austauschen beim Überfahren mit der Maus, und eine Technik, die wir wählen könnten, ist die Änderung des Attributs xlink:href mit JavaScript, wenn ein solches Ereignis ausgelöst wird. Da wir in diesem Artikel eine externe Datei mit dem oben beschriebenen Shim verwenden, können wir diese Technik nicht zuverlässig nutzen (wiederum wird das use-Element in IE ersetzt). Meine Empfehlung ist, einfach per CSS-Klassen ausblenden/anzeigen (Technik #1 im Artikel Swapping Out SVG Icons) und sicherstellen, dass Sie den SVG-Klon selbst ansprechen.
Wenn wir die Inline-SVG-Definition direkt am Anfang unserer Seite einfügen (z. B. direkt nach dem öffnenden <body>-Tag), haben wir dieses Problem nicht und die Technik des Manipulierens des xlink:href-Attributs ist in Ordnung.
Selektor-Beispiele
Um die obigen Punkte kristallklar zu machen, hier ist ein CSS-Selektor, der in Browsern funktionieren würde, die externe SVG-Definitionen vollständig unterstützen, aber fehlschlägt, wenn svg4everybody IE pollyfills
.my-svg use {
fill: red;
}
Es stellt sich heraus, dass es keinen wirklichen Bedarf oder Vorteil gibt, use anzusprechen, also ändern Sie es einfach wie folgt, um für alle Fälle zu funktionieren
.my-svg {
fill: red;
}
Während wir über Selektoren sprechen, sollten wir diese Gelegenheit nutzen, um darauf hinzuweisen, dass Sie nicht mit etwas wie dem Folgenden in die ursprüngliche SVG-Definition „hineingreifen“ können
svg.parent path.child { /* won't work! */ }
Das Gleiche würde für den Versuch gelten, etwas im Def selbst über die geklonte Instanz zu stylen, sei es eine Form, ein Pfad, eine Gruppe usw. Es mag offensichtlich sein, aber dies ist hier nur ein Problem, weil wir die use xlink:href-Strategie verwenden.
Gotcha Zwei: Zusammenarbeit mit einem Designer
Wenn Ihre Icons im Allgemeinen nur eine Farbe verwenden, ist das Anwenden von CSS-Styling auf eine geklonte Instanz „in einem Rutsch“ trivial mit: fill: <Ihre-Farbe>. Für solche Fälle muss der Designer des Projekts darauf achten, die Vektorgrafiken zu erstellen, indem er entweder nur schwarze Füllungen mit transparenten Strichen oder nur Pfaddaten (transparente Füllungen und Striche) verwendet. Sie können immer noch Striche über CSS anwenden, wenn Sie dies benötigen.
Um zu verstehen, warum dies so ist, müssen wir zuerst verstehen, wie unsere Vektoranwendung SVG exportiert.
Ich verwende Adobe Illustrator, aber wenn Sie ein anderes Vektorprogramm wie Inkscape oder Sketch usw. verwenden, sollten Sie die Dokumentation dieser Software konsultieren, um zu sehen, ob ihr Verhalten mit dem Folgenden übereinstimmt. Im schlimmsten Fall können Sie die Dateien auf verschiedene Weise exportieren, wie ich im Folgenden beschreibe, und testen, wie das von Ihrer Anwendung generierte SVG aussieht.
Illustrator SVG Export Verhalten
Zum Zeitpunkt der Erstellung exportiert die neueste Version von Illustrator CC SVG wie folgt
- Wenn Sie keinen Füll- oder Strich definieren oder nur eine Füllung definieren, diese Füllung aber *schwarz* ist (vollständig schwarz, wie
#000), enthalten die exportierten SVG-Pfade und Formen keine Füll- oder Strichattribute
<path ... positional information ... >
<rect ... positional information ... >
- Wenn Sie eine nicht-schwarze Füllung definieren oder einen Strich (beliebiger Farbe, einschließlich *schwarz*) definieren, enthalten die entsprechenden Pfade und Formen des exportierten SVG Strich- und/oder Füllattribute wie
<path stroke="#000000" ... >
<rect fill="fabdad" ... >
Diese Präsentationsattribute sind immer durch CSS überschreibbar, wenn Sie einen Stil direkt auf das SVG-Symbol, den Pfad, die Form usw. anwenden. Die Einschränkungen beim Anwenden von CSS auf eine *geklonte Instanz* (nicht direkt) werden als nächstes beschrieben.
Schwarze Füllung Exportieren / Strich Transparent
Wenn Ihr Quell-SVG mit ausschließlich schwarzen Füllungen (ohne Striche) oder nur mit Pfaden exportiert wurde, haben Sie viel Flexibilität, da Sie einen Strich oder eine Füllung über CSS anwenden können.

In diesem ersten Beispiel (beachten Sie, dass ich SCSS-Syntax verwende) wenden wir eine CSS-Füllung und einen Strich auf die geklonte Instanz an
.filled-instance {
stroke: #cc8ac1;
stroke-width: 5px;
fill: lighten(#cc8ac1, 20%);
}
Sie können auch einen umrandeten Effekt erzielen, indem Sie einfach die Füllung deaktivieren und einen Strich über CSS anwenden
.filled-instance-off {
stroke: #d08aaf;
stroke-width: 5px;
fill: transparent;
}
Der Grund, warum dies so wunderbar funktioniert, ist, dass unsere SVG-Definition keine definierten Füll- oder Strichattribute hat und daher unser CSS angewendet wird und alles in Ordnung ist.
Strich Exportieren / Füllung Transparent

Die schlechte Nachricht ist, dass Sie dem Strich auf der geklonten Instanz keinen Stil zuweisen können (denken Sie daran, unsere geklonte Instanz verweist in diesem Beispiel wiederum auf eine SVG-Definition, die wir mit „nur Strich“ erstellt haben). Wir können auch keine Füllung auf unsere geklonte Instanz anwenden, da unsere SVG-Formen jetzt fill="none" haben und dies Vorrang hat)
.stroked-instance {
stroke: green; /* nothing happens */
fill: red; /* nothing happens */
}
Es ist ähnlich wie bei HTML/CSS, wie
<div id="very-strong">
<span>still green.</span>
</div>
#very-strong { color: red; }
span { color: green; } /* I'm the actual element, so I win. */
Einige Workarounds
Sie sollten diese Situation wahrscheinlich ganz vermeiden, indem Sie schwarze Füllungen mit transparenten Strichen oder nur Pfade exportieren, aber wenn Sie aus irgendeinem Grund immer noch möchten, dass Ihre Stile wirksam werden, müssen Sie stattdessen das SVG-Symbol *direkt* mit etwas wie folgendem stylen
symbol#completed-copy-stroked [stroke] {
stroke: #dd6435;
stroke-width: 5px;
}
Beachten Sie, dass der Teil symbol des obigen Selektors unnötig ist, aber hier zur Klarheit verwendet wird, welches Element wir ansprechen
Auch dies ist bei der Verwendung eines Inline-SVG mit geklonten Instanzen nicht wirklich ideal, da wir, wo immer möglich, Stile auf unsere geklonten Instanzen anwenden möchten.
Eine weitere Technik, die Sie immer verwenden können, ist, einfach Klassen innerhalb des Quell-SVG hinzuzufügen und diese direkt über CSS anzusprechen. Diese Stile sind *global*, was ein Problem sein kann oder auch nicht – das müssen Sie für Ihren Fall entscheiden. Diese Technik funktioniert unabhängig davon, wie Sie das SVG exportiert haben. Da Sie eine CSS-Klasse von Hand hinzufügen, steht sie Ihnen zur Verfügung (wenn auch direkt – wir sprechen das Unterelement der SVG-Definition direkt an und stylen nicht über eine geklonte Instanz)
.ibestrokin {
stroke: magenta;
stroke-width: 5px;
}
.istrokeittotheeast {
stroke: green;
stroke-width: 7px;
}
Vielleicht zeige ich mein Alter, aber ich muss unweigerlich an Clarence Carter denken, wenn wir über „Stroking“ sprechen.
Meiner Meinung nach ist es nicht ideal, nur das SVG direkt stylen zu können (und nicht die geklonte Instanz). Daher empfehle ich, Striche in Fällen, in denen Sie Inline-SVG und geklonte Instanzen verwenden, komplett zu vermeiden. Wenn Sie bereits Kunstwerke mit definierten Strichen haben, können Sie überlegen, diese vor dem Export über etwas wie *Kontur umwandeln* in Pfade umzuwandeln.
Sehen Sie den Pen Inline SVG Fill and Stroke von Rob Levin (@roblevin) auf CodePen.
Nachbearbeitung
Eine weitere Überlegung ist, wenn Sie eine Nachbearbeitungsbibliothek wie grunt-svgstore verwenden, um Füllungen und Striche zu bereinigen. In diesem Fall hat das generierte SVG möglicherweise überhaupt keine expliziten Füll- oder Strichattribute, und nur Pfadinformationen bleiben in der resultierenden Definitionsdatei erhalten. In diesem Fall möchten Sie auf jeden Fall alle Striche in Pfade umwandeln oder riskieren, die entsprechenden sichtbaren Linien ganz zu verlieren. Alternativ sollten Sie nicht verlangen, dass Striche vom Nachbearbeiter entfernt werden (aber einige der zuvor diskutierten Probleme in Kauf nehmen). Kurz gesagt, wenn Ihre Kunstwerke wirklich einen Strich haben müssen, müssen Sie das SVG direkt ansprechen.
Schlussfolgerungen
Die Quintessenz ist also, dass Sie eine Entscheidung mit dem Designer treffen müssen, ob Sie alle Füllungen und Striche vollständig über CSS steuern möchten – in diesem Fall sollten Sie nur Pfade mit transparenten Füllungen und Strichen verwenden (oder schwarze Füllungen, wenn Sie diese zur Referenz behalten möchten) – oder ob es mehr Sinn macht, mit sinnvollen Standardwerten zu beginnen und diese dann bei Bedarf über CSS zu überschreiben. Wenn Sie Inline-SVG verwenden und bevorzugen, auf geklonte Instanzen zu stylen (nicht direkt auf das SVG), empfehle ich, einfach Pfade zu verwenden.
Gotcha Drei: Farbunterschiede erzielen
Einer der angeblichen Vorteile der Verwendung von SVG im Allgemeinen ist die flexible Stilkontrolle, die wir erhalten, da wir CSS auf einen SVG- *Pfad*, eine Form usw. anwenden können. Die Verwendung des use xlink:href-Mechanismus führt jedoch zu einem nicht aufgedeckten geklonten DOM-Baum, auf den unsere fill- oder stroke-Stile *global* auf das referenzierte SVG angewendet werden. Die Konsequenz daraus ist, dass alle geklonten Instanzen die gleiche Füllfarbe teilen.
Glücklicherweise gibt es einen Trick, mit dem wir zumindest eine eindeutige Farbe pro Instanz erhalten können. Wenn wir in die SVG-Definition selbst gehen, können wir fill=“currentColor” auf eine Form oder einen Pfad unserer Wahl anwenden. Was bewirkt das? Nun, der seit langem unterstützte CSS-Wert currentColor gibt an, dass die Farbe vererbt wird. Das bedeutet, dass wir eine Schriftfarbe weiter oben im Baum definieren können (z. B. auf den geklonten Instanzen selbst), und die Füllung für diesen Pfad oder diese Form erbt die Farbe. Ich bin mir nicht sicher, wer sich das zuerst ausgedacht hat, aber ich gebe Credit, wo ich es zuerst gesehen habe: Jenna Smiths Tweet.
Implementierung
Wir beginnen mit unserer Basisfüllung, die etwa so aussehen könnte
.icon-primary {
fill: #ccc;
color: #3bafda;
}
Diese Klassen würden auf die nicht aufgedeckte svg-Klon-Instanz angewendet werden
<svg class="icon-primary"> ...
Hier beginnt die Magie – unsere fill definiert die allgemeine Füllfarbe des Icons (in diesem Fall #cc), aber jetzt definiert unsere Schrift-color die geerbte Akzentfarbe, die wir wie oben beschrieben definiert haben, z. B.:
<path fill="currentColor" ... />

currentColor, um eine Akzentfarbe auf einem SVG-Pfad zu erzielenWenn Sie grunt-svgstore in Ihrem Build-Prozess verwenden (das Beispiel am Ende dieses Artikels tut dies), werden Sie es wahrscheinlich so konfigurieren, dass unerwünschter Ballast über die Eigenschaft cleanup entfernt wird, und diese Bibliothek behält Füllattribute mit dem Wert currentColor bei… Sie müssen sich also keine Sorgen machen, das benutzerdefinierte Attribut zu überschreiben, das oben definiert wurde.
Ich habe einen Sass-Mixin (bewusst abwärtskompatibel bis 3.2) dafür erstellt
@mixin svgColors($fill: false, $color: false, $patchCurrentColorForIE: false) {
@if $fill {
fill: $fill;
}
@if $color {
color: $color;
}
}
Und ich rufe ihn mit etwas wie folgendem auf
.icon-primary {
@include svgColors($neutralColor, $primaryColor, true);
}
Wenn Sie sich fragen, was es mit dem Parameter $patchCurrentColorForIE auf sich hat, habe ich ihn für die Icons dort, die keine mehreren Farben benötigen und daher den Shim nicht anwenden müssen.
Andere Techniken für Farbunterschiede
Zusätzlich zur Verwendung der oben genannten currentColor-Technik können Sie auch eine preserve---Attributfunktion verwenden, die jetzt in grunt-svgstore verfügbar ist. Sie funktioniert so, dass, wenn Sie preserve-- als Präfix für ein beliebiges gültiges Attribut im Quell-SVG verwenden, dieses Attribut im resultierenden SVG erhalten bleibt (wobei das preserve---Präfix entfernt wird). Zum Beispiel würde preserve--stroke nur stroke in der Ausgabe-SVG-Definition ergeben.
Eine weitere Technik, die Sie in Betracht ziehen können, wenn Sie sich fragen, wie Sie Farbunterschiede erzielen können – in diesem Fall für ein background-image – ist, die Vorgehensweise zu wählen, ein data-uri eines SVG zu verwenden, aber zuerst eine Suche und Ersetzung des fill-Werts durchzuführen, wie hier beschrieben. Dieser Ansatz ist jedoch etwas außerhalb des Rahmens und vom Thema dieses Artikels abweichend, da er einen nicht cachebaren data-uri verwendet und somit unser Hauptziel, eine cachebare externe SVG-Definitionsdatei zu verwenden, konterkariert.
Gotcha Vier: jQuery wirft Fehler
Wenn Sie jQuery auf Ihrer Seite eingebunden haben, führt ein direkter Klick auf ein gerendertes svg use-Element wahrscheinlich dazu, dass jQuery einen Fehler auslöst, der in ihrem Bug-Tracker dokumentiert ist. Es ist tatsächlich etwas knifflig, diesen Fehler zu reproduzieren, da Sie wahrscheinlich ein umschließendes Element haben werden, das als Anker oder Schaltfläche dient – und dieses Element hat die größere Trefferfläche –, aber er tritt erneut auf, wenn Sie direkt auf das Icon selbst klicken. Hier ist der bevorzugte Workaround
svg { pointer-events: none; }
Da pointer-events *vererbt* werden, bewirkt dies, dass auch alle „Unterelemente“ des SVG nicht auf pointer-events reagieren. Sobald Sie dies eingerichtet haben, sollten Sie darauf achten, dass die gesamte Ereignisbehandlung (wie z. B. ein JavaScript click-Handler) von einem Elternelement und nicht vom nicht aufgedeckten SVG-Klon selbst übernommen wird – eine Schaltfläche oder ein Anker sind offensichtliche Beispiele für umgebende Elemente, die in diesem Fall die Ereignisbehandlung übernehmen müssten.
Wenn Sie Maus- oder Pointer-Ereignisse für Animationen oder Ähnliches auf dem SVG selbst behandeln möchten, sollten Sie wahrscheinlich erwägen, für dieses spezielle SVG einfach ein img oder einen CSS-background-Tag zu verwenden; dies macht das Problem irrelevant.
Gotcha Fünf: GitHub Diffs
Ein Anliegen, das wir hatten, war, dass die SVG-Diffs für einen potenziellen Code-Reviewer ziemlich archaisch sind. Chris Coyier wies mich darauf hin, dass GitHub kürzlich eine tolle SVG-Anzeigefunktion eingeführt hat, die es ermöglicht, eine Ansicht des *Blobs* umzuschalten. Sehr praktisch.

Darüber hinaus ist eine teamweite Richtlinie, solche SVG-Arbeiten in separaten Commits zu halten (damit sie keine bedeutsameren Codeänderungen *trüben*), wahrscheinlich die pragmatischste Wahl hier.
Ein funktionierendes Beispiel
Ich habe ein „Spielzeugbeispiel“ eingerichtet, das hoffentlich hilfreich ist. Es implementiert Inline-SVG mit einem Grunt-Workflow und setzt auf eine cachebare externe SVG-Definitionsdatei. Beachten Sie, dass dieses Beispiel IE9 und höher erfordert.
Wenn Sie noch nicht bereit sind, dies einzurichten, hier ist eine Demoseite dessen, was wir bereitstellen werden.
Wenn Sie IE8 und darunter unterstützen müssen, können Sie auf ein PNG-Bild mit demselben Namen wie Ihr SVG (aber mit der .png-Erweiterung) zurückgreifen. Die Einrichtung wird in den Anweisungen für die svg4everybody-Bibliothek beschrieben, die wir bereits verwenden, also fangen Sie dort an.
Um das Beispiel auszuführen, benötigen Sie Folgendes installiert
Führen Sie die folgenden Befehle in Ihrem Terminal aus, um das Beispiel abzurufen und lokal bereitzustellen
Je nach Systemkonfiguration müssen Sie möglicherweise sudo vor den beiden folgenden npm install-Befehlen verwenden
# Install the Buttons example and set up npm dependencies
git clone -b svg-inline-experiments --single-branch https://github.com/unicorn-ui/Buttons.git Buttons && cd Buttons && npm install
# Install the SVG specific dependencies and run example
pushd svg-builder && npm install && grunt && popd && grunt dev
Mit diesen Befehlen:
- Klonen Sie das Repository und greifen Sie nur auf den relevanten
svg-inline-experiments-Zweig zu - Installieren Sie die Node-Abhängigkeiten von Buttons
- Installieren Sie die Node-Abhängigkeiten des SVG-Builders
- Führen Sie unseren Grunt-Entwicklungsworkflow aus, der die Inline-SVG-Definitionen des Beispiels erstellt und auch die Beispielseite erstellt
Abhängig von Ihrer Konfiguration sollte der letzte Schritt das Öffnen der folgenden Seite in Ihrem Standardbrowser Ihres Systems zur Folge haben (andernfalls besuchen Sie https://:8000 manuell)

Wenn Sie diese Einrichtung umkehren möchten, um Ihre eigene Projekteinrichtung zu informieren, sind die Dateien, auf die Sie sich beziehen sollten:
styleguide/includes/svg.htmlzeigt die Markup für die Erstellung von SVG-Instanzenstyleguide/scss/module/_svgs.scsszeigt die CSS-Stile, die auf unsere SVG-Icons angewendet werdensvg-builder/Gruntfile.jseine funktionierende Grunt-Konfiguration, die speziell für Inline-SVG angepasst iststyleguide/pages/index.htmlDas einzig wirklich Bemerkenswerte in dieser Datei ist, dass wirsvg4everybody.min.jseinbinden
Schlussfolgerungen
Nachdem die oben genannten Herausforderungen erfolgreich bewältigt wurden, behaupte ich, dass Teams, die moderne Webanwendungen entwickeln, Inline-SVG definitiv in Betracht ziehen sollten. Unicorn-UI bereitet die Implementierung eines „interaktiven Spielplatzes“ für unsere kürzlich veröffentlichten Buttons 2.0 Beta vor, und aus offensichtlichen Gründen werden wir Inline-SVG für dieses Projekt definitiv nutzen… vielleicht sollten Sie es auch für Ihr nächstes Projekt in Betracht ziehen.
Als Nachtrag für fortgeschrittene SVG-Nutzung müssen Sie sich unbedingt diesen Vortrag ansehen! Er geht tief auf Browserunterstützung und noch mehr Eigenheiten ein, die Sie vermeiden möchten.
Danke Nico… das werde ich mir nach Feierabend ansehen.
Wenn der SVG-Code, der aus Ihrem Grafikprogramm exportiert wird, Präsentationsattribute (Strich-/Füllfarben, die als Attribute angegeben sind) enthält, können Sie den Browser dazu zwingen, diese zu ignorieren und die Werte zu verwenden, die Sie in Ihrem Stylesheet für die einzelnen Icons angeben, mit einer einfachen Regel
[Hinweis: Diese Regel sollte sich in derselben Datei wie Ihre Icon-Definitionen befinden. Wenn Sie also externe Dateien verwenden, aber die Grafiken beim Laden per AJAX in Ihre Hauptdatei integrieren, wenn externe Referenzen nicht unterstützt werden, müssen Sie die Regel sowohl Ihrer externen Datei als auch Ihrem Haupt-Stylesheet hinzufügen.]
Der
*-Selektor mag am unteren Ende der CSS-Selektorspezifität stehen, aber er überschreibt immer noch Präsentationsattribute – und sowohl Illustrator als auch Inkscape verwenden Präsentationsattribute für Farbinformationen.Jetzt können Sie Dinge tun wie
Die Grafiken innerhalb jedes Icons erben die Stile.
Natürlich funktioniert das nur für einfache, einfarbige Icons. Wenn Sie eine nuanciertere Kontrolle wünschen, müssen Sie sich in den Code einarbeiten und die SVG-Stilkaskadenregeln kennenlernen.
Amelia, danke für das Teilen. Das ist ein interessanter Ansatz und ich bin auf jeden Fall daran interessiert, damit zu experimentieren, um besser zu verstehen, wie er in der Praxis funktionieren wird.
Ich stimme zu, dass die Verwendung von
*bedauerlich ist, ebenso wie die zusätzlichen Präsentationsdaten in der SVG-Definition (wenn sie gegen das beabsichtigte Ziel wirken, dann sehe ich sie als zusätzliches Gewicht und vielleicht lohnt es sich, sie einfach gar nicht zu exportieren). Mein Bauchgefühl ist also, dass das Exportieren ohne die Präsentationsattribute insgesamt immer noch ein Gewinner ist. Ich würde mich freuen zu hören, ob Sie dem zustimmen?Definitiv. Aber manchmal ist es einfacher zu überschreiben, als sich einzuarbeiten und den Code zu ändern. Oder vielleicht möchten Sie in einigen Anwendungsfällen Standardfarben in Ihren Icon-Definitionen festlegen, aber trotzdem die Möglichkeit haben, sie je nach Anwendungsfall zu ändern. (Wortspiel nicht beabsichtigt…)
Hallo Amelia, funktioniert das definitiv auch für Strichfarben? Mit Füllungen funktioniert es, aber mit Strichen nicht.
Vergessen Sie es; ich habe das Problem gefunden. Ich habe
[role=img]als Selektor verwendet, um die Erbschaft einzustellen. Obwohl dies für die Füllung funktionierte, tat es das nicht für den Strich. Was seltsam erscheint.Vielen Dank für den Tipp.
Oh je, Entschuldigung für den dreifachen Post hier.
Ich hatte nicht bemerkt, dass das Symbol, auf dem ich die Füllung gesetzt habe, seine Füllung nicht im SVG hatte. Also überschreiben
[role=img](undsvg) in meinem Fall nicht die Präsentationsattribute des SVG. (Symbole und use/xlink mit einer externen CSS-Datei.)Für Nummer #3 denke ich, dass
<use>-Elemente auf den Shadow DOM mit::shadow- oder/deep/-Selektoren zugreifen können, aber die Browserkonsistenz ist lückenhaft.Ian, ja, die guten alten Cross-Browser, huh; trotzdem ein interessanter Tipp (besonders für Debugging-Zwecke). Würden Sie einen Pen oder ein expliziteres Beispiel in Markdown-Kommentar hier teilen?
Hallo Rob,
Die von mir erwähnten Selektoren sind Teil des Entwurfs, der im April dieses Jahres veröffentlicht wurde. Da sie so neu sind, werden sie nicht wirklich gut unterstützt – aber Blink entspricht den Regeln, trotz eines Fehlers, der verhindert, dass die CSS korrekt berechnet wird. Sie können einen Pen hier sehen
http://codepen.io/TigerC10/pen/LEYGoo
Ian, danke für den Link zum Pen. Sehr coole Sache, besonders zum Debuggen. Allein das Aktivieren dieser Chrome-Flags ist hilfreich, da man die vollständige Sichtbarkeit von #shadow-root für „Host“ erhält, was super praktisch ist.
Welches DevTool verwendest du im Browser? Ist es das integrierte Safari? Das habe ich noch nie gesehen.
Ja, ich benutze normalerweise Chrome für Devtools, aber ich habe viele hässliche Plugins und so weiter. Deshalb habe ich Safari benutzt, um die Screenshots etwas sauberer zu halten.
Es gibt eine Methode, die du übersehen hast und die ich für sehr effektiv halte: das Inline-Einbetten einer externen SVG-Datei in dein HTML.
Nachdem die Seite geladen ist, verwende ich jQuery AJAX, um den SVG-Inhalt direkt in mein HTML einzufügen. Das Ergebnis ist eine cachebare SVG-Datei, die von den Browsern gecacht wird, dir aber dennoch die Feinsteuerung über die CSS der SVG-Elemente ermöglicht UND es dir erlaubt, SVG-Elemente mit xlink:href zu referenzieren.
Ich benutze diese Methode und sie funktioniert großartig. Sehr einfach und effektiv.
Der größte Nachteil der Verwendung einer externen SVG ist, dass du die CSS-Farben der einzelnen SVG-Elemente nicht fein steuern kannst.
Danke fürs Teilen, Jake! Wenn du sagst: „Ergebnis ist eine cachebare SVG-Datei“ – meinst du, der Browser cached die JavaScript-Datei, die das Einfügen vornimmt?
Verwendest du JavaScript, um Farben vor dem Einfügen zu ändern und CSS inline hinzuzufügen? Stylst du auch die SVG-Defs direkt? Das ist cool, aber auch hier habe ich versucht, das „globale“ Styling zu vermeiden, wo immer möglich, und stattdessen das Styling auf die geklonte Instanz zu bevorzugen, wo immer möglich.
Ich wäre daran interessiert, ob dies erlaubt, die JS-Datei über eine andere Domain zu hosten, aber trotzdem die SVG einzufügen. Bei meinen Tests muss die externe SVG-Datei auf derselben Domäne liegen. Das könnte also ein Vorteil dieser Technik sein. Wenn du bereits einen Pen oder Test hast, den du teilen kannst, würde ich ihn gerne ansehen.
@Rob
Kannst du mehr Details zu diesem Fehler geben? Ich konnte ihn nicht reproduzieren.
Wenn es ein Problem ist, sehe ich nichts Falsches an deinem Vorschlag, CSS zu verwenden, um den Stil auf den Wert des Präsentationsattributs zu setzen, aber ich bin nie auf ein Problem mit
currentColorgestoßen.http://codepen.io/anon/pen/yyLNXx
Das oben Genannte funktioniert wie erwartet in IE11 unter Win7 und im IE10-Kompatibilitätsmodus (konnte den IE9-Modus in CodePen nicht testen). Was übersehe ich bei der Art und Weise, wie du deine Grafiken gestaltest?
Amelia, ich glaube, es gibt eine Verwechslung in Bezug auf die Tatsache, dass dieses Problem speziell bei der Verwendung von Inline-SVG auftritt, aber mit einer externen Datei und der Verwendung des svg4everybody-Polyfills (obwohl ich mir nicht sicher bin, ob der Polyfill erforderlich ist, um diesen Fall zu reproduzieren… so war mein Setup). Ich bin bei der Arbeit, also werde ich versuchen, später darauf zurückzukommen, wenn ich mehr Zeit habe. Ich kann sagen, dass es (wenn du das Problem reproduzieren möchtest) besser sein könnte, mit etwas Ähnlichem wie dem letzten Beispiel mit den
git clone-Anweisungen zu testen. Ich habe die bereits präsentierbare Buttons-Showcase-Funktion genutzt, um das Beispiel zusammenzustellen, daher ist es leider keine einfache „nackte“ Einrichtung, aber du solltest das mit den Informationen, die ich am Ende dieses Artikels gebe, zusammenstellen können. Ich werde das vielleicht selbst tun, wenn ich mehr Zeit habe, und es auf GitHub hochladen.Es ist definitiv schwierig, dieses Thema mit den Unterschieden bei der direkten Gestaltung von SVGs, der Verwendung externer Dateien, der Nachbearbeitung usw. zu diskutieren. Vielleicht brauche ich mehr visuelle Hilfsmittel, um diese Unterschiede zu verdeutlichen.
Amelia, ich habe das noch einmal überprüft und mit meinem Demo-Code und einem einfacheren Testfall getestet, und es sieht so aus, als hätte ich da einen Fehler gemacht. Ich habe das Gefühl, dass ich zu der Zeit, als ich den falsch-negativen Fall bemerkt habe, fehlerhaftes CSS hatte. In jedem Fall habe ich die aktualisierte Version ohne die erwähnten IE-Hacks in IE9-11 getestet und auch die neuesten FF/Safari/Chrome bestätigt, und sie funktioniert einwandfrei. Deshalb habe ich den Abschnitt Gotcha Three: Achieving Color Variation aktualisiert und eingereicht, also wird der Artikel hoffentlich heute aktualisiert. Danke, dass du darauf aufmerksam gemacht hast.
Danke fürs Nachschauen. Und ich bin froh zu wissen, dass ich keinen weiteren SVG-Fehler mehr im Gedächtnis behalten muss!
Ich habe eine etwas andere Technik auf der Kundenliste meines Unternehmens verwendet, die zwei farbige Logos enthält, bei denen die Farben je nach aktuellem „Blend“ der Website dynamisch geändert werden können.
Ich kombiniere die SVG-Logos dynamisch als
symbols in einer Datei mit WordPress, und das Root-svg-Tag hat eine Klasse von.client-logos(Quellcode hier anzeigen). Die Logos werden dann mituseinnerhalb einesspanmit der Klasse.client__logoauf der Seite eingebunden.Die einzelnen
paths haben keinefill-Attribute, sondern die Klassenclass="light"oderclass="dark". Die Füllung wird dann in CSS gesetzt, indem.client-logos(die Klasse dessvg-Elements, für Firefox und IE) und.client__logo(die Klasse des umgebenden Elements, für Chrome/Webkit) angesprochen werden, wie folgt:Diese Methode funktionierte fehlerfrei in IE9+ (mit svg4Everybody für
use-Unterstützung). Farben konnten sogar dynamisch mit Hover-Zuständen usw. geändert werden. Theoretisch könntest du mit Klassen in der SVG beliebig viele Farben hinzufügen.Hey Shaw, danke fürs Teilen. Ich denke, das ist ähnlich dem, was ich über die direkte Adressierung der SVG erwähnt habe. Eine Sache, die ich mich fragen würde, ist, ob deine dynamisch generierte WP-Datei gecacht wird oder nicht. Eine andere Sache (und viele Anwendungsfälle erfordern dies nicht) ist, ob du zwei Instanzen benötigst, die auf dieselbe Def-Datei verweisen, aber unterschiedliche Akzentfarben benötigen. Ich glaube, deine Strategie ist eher der globale Ansatz (was in Ordnung ist, aber etwas, das man berücksichtigen sollte).
Etwas, das mit svg4everybody, oder sogar einem anderen Shim, bequemer sein könnte, wäre, die SVG-Definition einfach für IE und andere Fälle am body anzubringen. Das Einbetten jedes einzelnen ist wahrscheinlich nicht besser, als die Def einfach auf die Seite zu schieben; dann könnten wir immer noch
useohne die Belästigung ansprechen. Das ist wohl etwas vom Thema deines Kommentars abweichend, aber ich habe daran gedacht, da du svg4everybody erwähnt hast.Danke für die Antwort. Die Farbänderung per CSS ist auf die „Blend“-Funktion zurückzuführen, bei der sich das gesamte Skin der Seite ändert. Der Benutzer erhält eine neue CSS-Datei, aber nicht unbedingt neue Inhalte für die Seiten, was bedeutet, dass die
use-Referenzen dieselben bleiben würden. Die Möglichkeit, den Stil dieser SVG-Logos über das CSS zu steuern, war mit Abstand der einfachste Ansatz, da ich keine Variationen innerhalb der SVG-Datei selbst für eine unbekannte Anzahl von Blends erstellen musste oder versuchte, die Icon-Referenzen per JavaScript auszutauschen.In Bezug auf das Caching der dynamischen SVG, in den Chrome-Netzwerk-Tools hat der Antwort-Header
Cache-Control:max-age=2592000, was ich in der .htaccess für alle Bilder gesetzt habe. Allerdings zeigen andere Bilder und CSS/JS einen Status von304 Not Modified, während diese SVG200 OKanzeigt. Irgendwelche Ideen, was da passieren könnte?Bezüglich des fehlenden Cachings, ja, deshalb habe ich erwähnt: „Ich würde mich fragen, ob deine dynamisch generierte WP-Datei gecacht wird oder nicht“, da es (ohne deine Implementierung genauer zu prüfen) so erscheinen würde, als hättest du die SVG-Def „als Inhalt“ eingefügt; du machst das nur dynamisch (was irgendwie cool ist und möglicherweise eine Anforderung für den Effekt ist, den du erzielen möchtest). Ich würde da pragmatisch sein. Was ist die Gesamtgrößenerhöhung? Unterstützt du Leute auf Mobilgeräten, die im Zug schauen, oder ist es eher eine „Show-off“-Seite? Auch hier bin ich mir nicht sicher, wie dynamisch deine Implementierung sein muss, und ich habe damit nur statische Icon-Sets eingerichtet, aber ich könnte mir etwas wie das Folgende vorstellen
sagen wir, du hättest drei „Themen“, die ein Benutzer wählen könnte: rot, grün, blau (der Einfachheit halber)
dein dynamischer Code ermittelt, was sie in der Vergangenheit angefordert haben (ich weiß nicht wie, vielleicht ein Cookie oder eine Datenbankabfrage usw.)
du lädst die entsprechende externe SVG-Def-Datei, die dann für diesen Benutzer cachebar ist, insbesondere wenn sie dieses Thema bei nachfolgenden Besuchen beibehalten
Ich entschuldige mich, wenn das völlig daneben ist, was du zu erreichen versuchst. Ich brainstorme nur, da die allgemeine Anwendungsfall von dynamischen externen cachebaren Dateien ein interessantes Problem zu lösen scheint.
Wenn du eine Lösung findest, poste bitte einen Link zu einem Gist, Pen usw. Danke, Shaw!
Nachdem ich meine Antwort und deinen ursprünglichen Beitrag noch einmal gelesen habe, möchte ich nur erwähnen, dass der Hauptunterschied bei dem, was ich vorschlage, darin besteht, dass deine Datei zwar dynamisch generiert wird, ich mich aber frage, ob es einen Unterschied machen würde, „vorkonfigurierte statische Dateien“ zu haben und der dynamische Teil nur die Wahl zwischen ihnen wäre. Es unterstützt deinen Anwendungsfall möglicherweise überhaupt nicht, ich weiß es nicht, aber mein Gedanke war, dass diese Dateien, da sie statisch sind, dann cachebar wären.
Ich habe das dynamische Caching-Problem möglicherweise gelöst, indem ich in WordPress eine Weiterleitung eingerichtet habe, die
clients.svgauf die dynamische SVG-Seite verweist. Da die tatsächliche .svg-Erweiterung vorhanden ist, scheint Chrome sie korrekt zu cachen und ordnungsgemäße304 Not Modified-Antworten zu erhalten.Dies ist definitiv eine „Show-off“-Seite, da wir eine Kreativagentur sind, aber ich habe versucht, das Erlebnis für Mobilgeräte so leicht wie möglich zu gestalten (obwohl es insgesamt immer noch ziemlich schwer ist), indem ich die Menge an Bildern und Dateien, wo immer möglich, begrenzt habe.
Ich denke, für diesen Anwendungsfall ist das Setzen der Farben in CSS am sinnvollsten. Der Benutzer erhält jedes Mal ein zufälliges Thema, wenn er auf den „Blend“-Button klickt, aber der Inhalt der Seite selbst ändert sich nicht unbedingt, sodass die SVG-Referenzen auf der Seite dieselben sind (
<use xlink:href="logo-att">).Da er bereits eine neue CSS-Datei erhält, die den Großteil des neuen Themas enthält, kann die Farbe einfach dort eingestellt werden, ohne dass eine weitere SVG-Datei generiert werden muss. Viel einfacher für Wartung und für das Hinzufügen neuer Themen.
Die dynamische SVG war nicht unbedingt eine Anforderung, aber ich wollte es zukünftig einfach machen, neue Logos hinzuzufügen, und das kann jetzt innerhalb von WordPress geschehen, ohne sich mit umständlichen Grunt-Prozessen zum Verketten von SVG-Dateien herumschlagen oder versuchen zu müssen, die SVG-Datei manuell zu pflegen.
Danke für den Austausch, es hat mir geholfen, tiefer in die Methode einzutauchen. Wenn ich diese dynamische SVG-Methode etwas verbessern kann, könnte sie ein nützliches WordPress-Plugin zum Generieren von SVG-Icons werden.
Ich habe ein paar Stolpersteine mit Inline-SVG und Angular gefunden.
Angular-Views verstehen xlink:href nicht von Haus aus. Du musst ein neues Modul erstellen, damit sie es verstehen. Das ist lösbar.
Wenn du Inline-SVG in einem ng-repeat platzierst, um eine Liste von Icons anzuzeigen, werden die Icons beim Laden der Seite nicht gerendert. Die Icons erscheinen nach bestimmten Ereignissen (kann mich gerade nicht erinnern). Ich konnte keine Lösung dafür finden. Ich werde einen Pen erstellen, um das zu veranschaulichen, wenn ich Zeit habe.
Danke für den Artikel.
Mouly, ich habe mich einmal zwei Wochen lang mit Angular beschäftigt und bin nicht viel weiter gekommen, daher bin ich wahrscheinlich nicht die richtige Person, um dich in die richtige Richtung zu lenken, tut mir leid (vielleicht ein anderer css-trick-Leser tut das ja doch!). Erstelle den Pen, wenn du Zeit hast, und poste ihn zurück. Danke, Mouly!
Bei der Arbeit an der Rushmore-Website und der Verwendung von React.js habe ich etwas Interessantes festgestellt, das das Leben viel einfacher macht.
Wenn du React verwendest und sowieso JavaScript zur Darstellung von allem verwendest (es ist möglich, serverseitig mit Node.js zu rendern), dann helfen die use-Elemente nicht wirklich. Der beste Ansatz ist in einem solchen Fall, immer Inline-SVG einzufügen.
Ein großer Vorteil ist, dass das Schreiben von CSS, das auf die SVG und ihre einzelnen Teile abzielt, viel, viel einfacher wird. Mit use-Tags wird das Ansprechen kleiner Teile einer SVG sehr unzuverlässig.
Zweitens, wenn du etwas wie browserify oder webpack verwendest, kannst du deine gesamte SVG-Datei als String in dein JS-Bundle einfügen, sodass du HTTP-Anfragen weiter reduzieren kannst und sie gleichzeitig cachebar sind. Offensichtlich kannst du, wenn du willst, immer noch AJAX-Aufrufe stattdessen verwenden.
Sam Ellis hat uns einen interessanten SVG-Gotcha mitgeteilt