I’ve talked a good bit about SVG’s <use>
around here and using it to build an icon system. The beauty of <use>
is that you can reference just a part of some SVG defined elsewhere and draw just that part somewhere else. That ability allows you to build a whole system out of it, solving the “many images in one request, because that’s super efficient” problem that we’ve solved in the past with CSS sprites and icon fonts.
But <use>
means inline SVG. It doesn’t help you when you want to use a part of a larger SVG in SVG-as-<img>
or SVG-as-background-image
. That’s where fragment identifiers come in.
Getting the SVG Ready For It
One way to do this is to lay out the SVG (sprite, I guess, let’s just call it a sprite) like a graphical “CSS” sprite.

We’re specifically doing it this way, because we ultimately are going to shift some viewBox
numbers around to only reveal a part of this image, just like we used to do with CSS sprites.
In this little mini demo, we’re using three icons that are 32×32 each. So the document is 32×96. We could think of the viewBox shenanigans this way:
Whole document viewBox | 0 0 32 96 |
Just show top icon viewBox | 0 0 32 32 |
Just show middle icon viewBox | 0 32 32 32 |
Just show bottom icon viewBox | 0 64 32 32 |
The viewBox
attribute goes: left, top, width, height. Note that second attribute, the top, notching up by 32 each time. We’re just showing a different part of the whole document.
Adding those special viewBox’s into the SVG itself
You can drop those special, specific viewBox
values into the SVG in a <view>
element, that is specifically for this:
<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" />
Now we’ll be able to reference and use those values from elsewhere.
The <view>
elements can be stand-alone like this, or they can actually wrap other elements, in which case that viewBox
takes hold when the ID matches, so
<!-- this viewBox takes over if current fragment identifer is #match-me -->
<view id="match-me" viewBox="0 64 32 32">
<rect ...>
</view>
Demo of this kind of thing in the spec.
Syntax for HTML
To apply those special viewBox
values to SVG-as-<img>
, you could do it like this:
<!-- top icon -->
<img src="sprite.svg#svgView(viewBox(0, 0, 32, 32))" alt="">
Or, if you set up <view>
elements already, you can just reference them by name:
<!-- middle icon -->
<img src="sprite.svg#icon-heart-view" alt="">
Syntax for CSS
You can declare a special viewBox
right in the image path in the CSS:
.icon-clock {
background: url("sprite.svg#svgView(viewBox(0, 0, 32, 32))") no-repeat;
}
Or reference a <view>
element if you have those set up:
.icon-clock {
background: url(sprite.svg#icon-clock-view) no-repeat;
}
Although… if you’re using SVG through CSS this way and went through the trouble to set up the SVG all spaced out like this, you might wanna just use the CSS sprite technique and shift the background around:
.icon-heart {
background: url("sprite.svg") no-repeat;
background-size: 32px 96px;
background-position: 0 -32px;
}
I just wanna stack the icons on top of each other.
If the icons all have the same viewBox
and you essentially just want to hide/show them as needed, this can get a little easier.
Design them all in the same space (or use a build tool that does it or whatever). Here, I’m putting each icon in its own group with a unique ID.

The trick to making the hide/show work then is embedding some CSS that 1) hides everything 2) reveals the one with a matching fragment identifier. CSS is up for the job, because of the :target
selector.
All together in the 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 Support
Can I Use tracks support for fragment identifier. Unfortunately, it’s not quite as simple as works-or-not because depending on the browser it might work in HTML and not CSS or have quirks.
Here’s my test page:
See the Pen SVG Fragment Identifiers in HTML and CSS by Chris Coyier (@chriscoyier) on CodePen.
I haven’t made super detailed browser support notes for this, but here are the highlights:
- Firefox does everything right.
- IE 11 does everything right. IE 9 & 10 are a little weird with
background-position
(squishing) but otherwise works with all. Current versions of Chrome/Safari/Opera (38/8/25) handle all the HTMLUpdate: If the<img>
techniques well, but none of the CSS techniques, including thebackground-position
one. Pre-Blink Opera was the same, interestingly enough.<svg>
referenced has correct width and height attributes on it, all the methods work as expected. At least it does now, as of Chrome (56) / Opera.- The only thing iOS 8.1 can handle is
<img>
referencing a<view>
. - The only thing Android 4.4 gets right is background-position (the one that’s not really using fragment identifiers at all). Android 5 matches current Chrome/Safari/Opera as above.
Linkage!
- Spec
- SVG Stacks by Simuari, which points to a demo by Erik Maelström and a demo by Bear Travis.
- Demo by Jorge Aznar
- Better SVG Sprites With Fragment Identifiers by Peter Gasston
- SVG Sprite Sheets by Bear Travis
Chris I was just trying to use an Svg fragment from an SVG Sprite for list-style-image but it doesn’t seem to work, do you think something like this could be possible:
Interesting. I haven’t heard of
view
before.In the browser test example, you’re using different SVGs in the
background-image
+background-position
test, which may be affecting the display of the clock icon.When I tested it locally and on a server, the
background-position
trick worked as expected. There may be something with how that SVG is being served that is preventing it from displaying correctly.It’s not a problem with the image file; something else is going on. If I open up the Chrome DOM inspector and edit the background-position values to the exact same values then it works as expected. So definitely a Chrome or webkit bug there; if you want to do a little more experimentation you could test whether it is specific to SVG images, whether it is affected by the view elements within the SVG or the viewBox attributes, and so on.
@Chris
Great write up, and great test page. I’m really hoping webkit will change to support fragments on CSS images, but it’s good to know that all these techniques work on HTML images in the latest versions of all major browsers.
@Amelia: I was able to get it to work locally and on a server using the same SVG. Here’s my test (slightly modified from the original): http://brokensquare.com/Code/svg-background-position/
I think something is off with Chrome and how the SVG is being served on Codepen.
Here’s an isolated demo on CodePen where I removed Normalize and the other examples, but it’s still not working: http://codepen.io/shshaw/pen/kIEFu
And here’s an identical test on my external server, but still referencing the same SVG file on CodePen: http://brokensquare.com/Code/svg-background-position/codepen.html
Something’s happening here in CodePen that Chrome doesn’t like.
Weird. After I closed the CodePen example and reopened it, Chrome started displaying the icons correctly. Perhaps it’s something in Chrome’s rendering engine when combined with the other SVG techniques?
@Shaw
Weird indeed. I can confirm the same erratic rendering with your test pen: sometimes it works, sometimes not. Right now I’ve got the page open in two different tabs, one shows the icons correctly and the other has the incorrect position.
nothing worked for me on
Chrome 38.0.2125.111
andFirefox 33.0.2
inOS X 10.10
This is very interesting, but (unless I’ve missed something) this is a manual process, isn’t it? Also, by using this process, can you change the image color?
Thanks!
@Allesandro
I’m not sure what you mean by a “manual process” — you need to create the correct markup and URLs and position your graphics appropriately, but you could say the same for PNG sprites, too.
You cannot use CSS to change the icon colours or styles when the icon is embedded as an image (whether using an HTML img element or CSS background/list image). The styles for the image are completely separate from the styles for the main page. There’s discussion about future SVG specs maybe having a way to pass in parameters or CSS variables to an image, but that’s still pretty hypothetical.
Thanks for the tests. Given the sketchy browser support, and the fact that one can’t customize colors (or other SVG styles) when using img elements, I don’t see myself using these kinds of SVG sprites anytime soon.
Chris, you write that “<use> means inline SVG”. Do you mean because of the lack of support in IE for external SVG?
I’m still experimenting but I tend to favor <use> with external SVG since it allows to use CSS in order to define:
up to two custom colors (using fill/color or stroke/color; this requires a SVG source that’s prepped up for that kind of use, but it’s not hard);
even more custom colors using CSS Custom Properties;
fill/no fill;
stroke-width/no stroke.
I’m using all this right now with inlined SVG, and I’m wondering if we should push for better browser support for the same techniques with external SVG.
I don’t get these SVG things. Why would I ever use something like this? I’ve followed all techniques you showed us here and I’m not nearly close of thinking to use any. Whats wrong with font icons, only anti aliasing thing? If I’m to use any of advantages of SVG (SVG specific css) I need to have bloated sausages of code in my HTML or/and to have 50+ components in my grunt/gulp workflow to take care of all things and their fallbacks. I can see a point of SVG for some complex illustrations but for current flat design trands, pictogram type icons all around, I simple don’t get it. Are you that bored and need fixings thing that ain’t broken?
Here’s a comparison: https://css-tricks.com/icon-fonts-vs-svg/
Both techniques solve the same problem: putting lots of images into a single request. It’s just SVG mostly does a better job from lots of different perspectives.
Cool! Is there a reason to not… ahem.. use in SVGs in backgrounds? Seems to work pretty well for me.
I’ve been experimenting with a sprite approach where the symbols are defined in the defs, all positioned over each other. Then I employ the
use
tag and set the coordinates there. I use CSS background position with percentage values, and the icon scales. Its pretty nice and seems to work everywhere.Here’s a demo:
Also did a write up on my blog about how to approach styling in different ways.
http://noahblon.com/coloring-svgs-in-css-background-images/
i’m “shifting” around with spritecssgenerator.formfcw.com
think it’s still the most comfortable way, but the view-method also sounds interesting