Ich habe hier schon viel über das SVG-<use>-Element gesprochen und wie man es für den Aufbau eines Icon-Systems nutzt. Das Schöne am <use>-Element ist, dass man nur einen Teil eines woanders definierten SVGs referenzieren und nur diesen Teil woanders zeichnen kann. Diese Fähigkeit ermöglicht es, ein ganzes System daraus aufzubauen und das Problem des „viele Bilder in einer Anfrage, weil das super effizient ist“, zu lösen, das wir früher mit CSS-Sprites und Icon-Fonts gelöst haben.
Aber <use> bedeutet Inline-SVG. Es hilft nicht, wenn man einen Teil eines größeren SVGs in SVG-als-<img> oder SVG-als-background-image verwenden möchte. Hier kommen Fragmentidentifikatoren ins Spiel.
Vorbereitung des SVG darauf
Eine Möglichkeit, dies zu tun, ist, das SVG (Sprite, denke ich, nennen wir es einfach Sprite) wie ein grafisches „CSS“-Sprite anzuordnen.

Wir tun dies speziell, weil wir letztendlich einige viewBox-Zahlen verschieben werden, um nur einen Teil dieses Bildes anzuzeigen, genau wie wir es früher mit CSS-Sprites getan haben.
In dieser kleinen Mini-Demo verwenden wir drei Icons, die jeweils 32×32 Pixel groß sind. Das Dokument ist also 32×96 Pixel groß. Wir könnten die viewBox-Spielereien so betrachten:
Gesamtes Dokument viewBox |
0 0 32 96 |
Nur oberes Icon anzeigen viewBox |
0 0 32 32 |
Nur mittleres Icon anzeigen viewBox |
0 32 32 32 |
Nur unteres Icon anzeigen viewBox |
0 64 32 32 |
Das Attribut viewBox lautet: links, oben, breite, höhe. Beachten Sie das zweite Attribut, oben, das jeweils um 32 erhöht wird. Wir zeigen einfach einen anderen Teil des gesamten Dokuments an.
Hinzufügen dieser speziellen viewBoxs zum SVG selbst
Sie können diese speziellen, spezifischen viewBox-Werte in einem <view>-Element in das SVG einfügen, das speziell dafür gedacht ist.
<view id="icon-clock-view" viewBox="0 0 32 32" />
<view id="icon-heart-view" viewBox="0 32 32 32" />
<view id="icon-arrow-right-view" viewBox="0 64 32 32" />
Nun können wir diese Werte von woanders referenzieren und verwenden.
Die <view>-Elemente können eigenständig so stehen oder andere Elemente umschließen. In diesem Fall wird die viewBox wirksam, wenn die ID übereinstimmt, also:
<!-- this viewBox takes over if current fragment identifer is #match-me -->
<view id="match-me" viewBox="0 64 32 32">
<rect ...>
</view>
Demo dieser Art von Funktion in der Spezifikation.
Syntax für HTML
Um diese speziellen viewBox-Werte auf SVG als <img> anzuwenden, könnten Sie es so machen:
<!-- top icon -->
<img src="sprite.svg#svgView(viewBox(0, 0, 32, 32))" alt="">
Oder, wenn Sie bereits <view>-Elemente eingerichtet haben, können Sie sie einfach nach Namen referenzieren:
<!-- middle icon -->
<img src="sprite.svg#icon-heart-view" alt="">
Syntax für CSS
Sie können eine spezielle viewBox direkt im Bildpfad in CSS deklarieren:
.icon-clock {
background: url("sprite.svg#svgView(viewBox(0, 0, 32, 32))") no-repeat;
}
Oder ein <view>-Element referenzieren, wenn Sie diese eingerichtet haben:
.icon-clock {
background: url(sprite.svg#icon-clock-view) no-repeat;
}
Obwohl… wenn Sie SVG über CSS auf diese Weise verwenden und sich die Mühe gemacht haben, das SVG auf diese Weise auseinanderzulegen, möchten Sie vielleicht einfach die CSS-Sprite-Technik verwenden und den Hintergrund verschieben.
.icon-heart {
background: url("sprite.svg") no-repeat;
background-size: 32px 96px;
background-position: 0 -32px;
}
Ich möchte die Icons einfach übereinander stapeln.
Wenn die Icons alle die gleiche viewBox haben und Sie sie im Grunde nur nach Bedarf ein-/ausblenden möchten, kann dies etwas einfacher werden.
Gestalten Sie sie alle im gleichen Bereich (oder verwenden Sie ein Build-Tool, das dies tut, oder was auch immer). Hier platziere ich jedes Icon in eine eigene Gruppe mit einer eindeutigen ID.

Der Trick, um das Ein-/Ausblenden zu ermöglichen, besteht dann darin, etwas CSS einzubetten, das 1) alles ausblendet und 2) das mit einem übereinstimmenden Fragmentidentifikator einblendet. CSS ist dafür geeignet, wegen des :target-Selectors.
Alles zusammen im SVG
<defs>
<style>
g {
display: none;
}
g:target {
display: inline;
}
</style>
</defs>
<g id="icon-clock">
<path d="M20.6,23.3L14,16.7V7.9h4v7.2l5.4,5.4L20.6,23.3z M16-0.1c-8.8,0-16,7.2-16,16s7.2,16,16,16s16-7.2,16-16S24.8-0.1,16-0.1z
M16,27.9c-6.6,0-12-5.4-12-12s5.4-12,12-12s12,5.4,12,12S22.6,27.9,16,27.9z"/>
</g>
<g id="icon-heart">
<path d="M32,11.2c0,2.7-1.2,5.1-3,6.8l0,0L19,28c-1,1-2,2-3,2s-2-1-3-2L3,18c-1.9-1.7-3-4.1-3-6.8C0,6.1,4.1,2,9.2,2
c2.7,0,5.1,1.2,6.8,3c1.7-1.9,4.1-3,6.8-3C27.9,1.9,32,6.1,32,11.2z"/>
</g>
<g id="icon-arrow-right">
<path d="M32,15.9l-16-16v10H0v12h16v10L32,15.9z"/>
</g>
Browser-Unterstützung
Can I Use verfolgt die Unterstützung für Fragmentidentifikatoren. Leider ist es nicht ganz so einfach wie funktioniert oder nicht, denn je nach Browser funktioniert es möglicherweise in HTML und nicht in CSS oder hat Eigenheiten.
Hier ist meine Testseite
Siehe den Pen SVG Fragment Identifiers in HTML and CSS von Chris Coyier (@chriscoyier) auf CodePen.
Ich habe keine super detaillierten Browser-Support-Notizen dafür gemacht, aber hier sind die Highlights:
- Firefox macht alles richtig.
- IE 11 macht alles richtig. IE 9 & 10 sind mit
background-positionetwas seltsam (Quetschen), aber ansonsten funktioniert alles. Aktuelle Versionen von Chrome/Safari/Opera (38/8/25) behandeln alle HTML-Update: Wenn das referenzierte<img>-Techniken gut, aber keine der CSS-Techniken, einschließlich derbackground-position-Methode. Pre-Blink Opera war interessanterweise dasselbe.<svg>korrekte Breiten- und Höhenattribute hat, funktionieren alle Methoden wie erwartet. Zumindest jetzt, mit Chrome (56) / Opera.- Das Einzige, was iOS 8.1 verarbeiten kann, ist
<img>, das auf ein<view>verweist. - Das Einzige, was Android 4.4 richtig macht, ist
background-position(diejenige, die eigentlich gar keine Fragmentidentifikatoren verwendet). Android 5 entspricht dem aktuellen Chrome/Safari/Opera wie oben.
Verlinkung!
- Spezifikation
- SVG Stacks von Simurai, das auf eine Demo von Erik Maelström und eine Demo von Bear Travis verweist.
- Demo von Jorge Aznar
- Bessere SVG-Sprites mit Fragmentidentifikatoren von Peter Gasston
- SVG-Sprite-Sheets von Bear Travis
Chris, ich habe gerade versucht, ein SVG-Fragment aus einem SVG-Sprite für `list-style-image` zu verwenden, aber es scheint nicht zu funktionieren. Glaubst du, etwas wie das wäre möglich?
Interessant. Von `view` hatte ich noch nie gehört.
Im Browser-Testbeispiel verwenden Sie unterschiedliche SVGs in den Tests für
background-image+background-position, was die Anzeige des Uhr-Icons beeinträchtigen könnte.Als ich es lokal und auf einem Server getestet habe, funktionierte der
background-position-Trick wie erwartet. Es gibt möglicherweise etwas damit, wie dieses SVG bereitgestellt wird, das verhindert, dass es korrekt angezeigt wird.Es ist kein Problem mit der Bilddatei; etwas anderes ist im Gange. Wenn ich den Chrome DOM-Inspektor öffne und die
background-position-Werte *auf die exakt gleichen Werte* ändere, funktioniert es wie erwartet. Es handelt sich also definitiv um einen Chrome- oder Webkit-Fehler; wenn Sie weiter experimentieren möchten, könnten Sie testen, ob er spezifisch für SVG-Bilder ist, ob er von denview-Elementen innerhalb des SVG oder denviewBox-Attributen beeinflusst wird und so weiter.@Chris
Tolle Zusammenfassung und tolle Testseite. Ich hoffe wirklich, dass Webkit sich ändert, um Fragmente in CSS-Bildern zu unterstützen, aber es ist gut zu wissen, dass all diese Techniken in den neuesten Versionen aller wichtigen Browser auf HTML-Bildern funktionieren.
@Amelia: Ich konnte es lokal und auf einem Server mit demselben SVG zum Laufen bringen. Hier ist mein Test (leicht modifiziert vom Original): http://brokensquare.com/Code/svg-background-position/
Ich glaube, mit Chrome und der Art und Weise, wie das SVG auf Codepen bereitgestellt wird, stimmt etwas nicht.
Hier ist eine isolierte Demo auf CodePen, bei der ich Normalize und die anderen Beispiele entfernt habe, aber es funktioniert immer noch nicht: http://codepen.io/shshaw/pen/kIEFu
Und hier ist ein identischer Test auf meinem externen Server, der aber immer noch auf dieselbe SVG-Datei auf CodePen verweist: http://brokensquare.com/Code/svg-background-position/codepen.html
Hier auf CodePen passiert etwas, das Chrome nicht mag.
Seltsam. Nachdem ich das CodePen-Beispiel geschlossen und wieder geöffnet hatte, begann Chrome, die Icons korrekt anzuzeigen. Vielleicht liegt es an der Rendering-Engine von Chrome in Kombination mit den anderen SVG-Techniken?
@Shaw
Wirklich seltsam. Ich kann dieselbe erratische Darstellung mit Ihrem Test-Pen bestätigen: Manchmal funktioniert es, manchmal nicht. Im Moment habe ich die Seite in zwei verschiedenen Tabs geöffnet, einer zeigt die Icons korrekt an und der andere hat die falsche Position.
Nichts funktionierte bei mir auf
Chrome 38.0.2125.111undFirefox 33.0.2unterOS X 10.10.Das ist sehr interessant, aber (sofern ich nichts übersehen habe) ist das ein manueller Prozess, oder? Und kann man mit diesem Prozess die Bildfarbe ändern?
Danke!
@Alessandro
Ich bin mir nicht sicher, was Sie mit einem „manuellen Prozess“ meinen – Sie müssen die richtige Markup- und URL-Struktur erstellen und Ihre Grafiken entsprechend positionieren, aber dasselbe könnte man auch für PNG-Sprites sagen.
Sie können CSS nicht verwenden, um die Farben oder Stile von Icons zu ändern, wenn das Icon als Bild eingebettet ist (egal ob über ein HTML-
img-Element oder als CSS-Hintergrund-/Listenbild). Die Stile für das Bild sind vollständig von den Stilen der Hauptseite getrennt. Es gibt Diskussionen darüber, dass zukünftige SVG-Spezifikationen möglicherweise eine Möglichkeit bieten, Parameter oder CSS-Variablen an ein Bild zu übergeben, aber das ist noch ziemlich hypothetisch.Danke für die Tests. Angesichts der fragwürdigen Browserunterstützung und der Tatsache, dass man keine Farben (oder andere SVG-Stile) anpassen kann, wenn man
img-Elemente verwendet, sehe ich mich in nächster Zeit nicht mit diesen Arten von SVG-Sprites arbeiten.Chris, Sie schreiben, dass „<use> bedeutet Inline-SVG“. Meinen Sie das wegen des Mangels an Unterstützung in IE für externes SVG?
Ich experimentiere immer noch, aber ich bevorzuge
<use>mit externem SVG, da es die Verwendung von CSS ermöglicht, umbis zu zwei benutzerdefinierte Farben (mit
fill/coloroderstroke/color; dies erfordert eine SVG-Quelle, die für diese Art von Verwendung vorbereitet ist, aber das ist nicht schwierig);noch mehr benutzerdefinierte Farben mit CSS Custom Properties;
fill/keinfill;stroke-width/keinstroke.Ich verwende all dies gerade mit Inline-SVG und frage mich, ob wir eine bessere Browserunterstützung für dieselben Techniken mit externem SVG fordern sollten.
Ich verstehe diese SVG-Dinge nicht. Warum sollte ich so etwas jemals benutzen? Ich habe alle von Ihnen gezeigten Techniken befolgt und bin noch lange nicht so weit, dass ich denke, ich würde sie benutzen. Was ist falsch an Schrift-Icons, nur das Anti-Aliasing-Problem? Wenn ich irgendwelche Vorteile von SVG (SVG-spezifisches CSS) nutzen will, brauche ich aufgeblähte Code-Würste in meinem HTML oder/und muss 50+ Komponenten in meinem Grunt/Gulp-Workflow haben, um mich um all die Dinge und ihre Fallbacks zu kümmern. Ich sehe einen Sinn für SVG bei einigen komplexen Illustrationen, aber für aktuelle Flat-Design-Trends, Piktogramm-artige Icons überall, verstehe ich es einfach nicht. Sind Sie so gelangweilt und brauchen Dinge, die nicht kaputt sind?
Hier ist ein Vergleich: https://css-tricks.de/icon-fonts-vs-svg/
Beide Techniken lösen dasselbe Problem: viele Bilder in einer einzigen Anfrage zusammenzufassen. Es ist einfach so, dass SVG aus vielen verschiedenen Blickwinkeln meistens besser abschneidet.
Cool! Gibt es einen Grund, SVGs nicht… äh… in Hintergründen zu verwenden? Funktioniert für mich ziemlich gut.
Ich habe mit einem Sprite-Ansatz experimentiert, bei dem die Symbole in den
defsdefiniert sind und alle übereinander positioniert sind. Dann verwende ich dasuse-Tag und setze die Koordinaten dort. Ich verwende CSSbackground-positionmit Prozentwerten, und das Icon skaliert. Es ist ziemlich nett und scheint überall zu funktionieren.Hier ist eine Demo
http://codepen.io/noahblon/pen/YPKjKr/
Ich habe auch einen Beitrag auf meinem Blog darüber geschrieben, wie man auf verschiedene Weise mit dem Styling umgeht.
http://noahblon.com/coloring-svgs-in-css-background-images/
Ich „verschiebe“ mich mit spritecssgenerator.formfcw.com.
Ich denke, es ist immer noch der komfortabelste Weg, aber die View-Methode klingt auch interessant.