Is There an Equivalent of Spriting for Svg Images in Web Pages

Is there an equivalent of spriting for SVG images in web pages?

You can use 'traditional' CSS sprite techniques to slice up SVG images with background position, here's a quick example, though it does get a little confusing if you also start using background-size. It's probably easier if you define a size on your SVG image:

<svg version="1.1" 
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="320"
height="240"
viewBox="0 0 320 240">

Do I use img, object, or embed for SVG files?

I can recommend the SVG Primer (published by the W3C), which covers this topic: http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML

If you use <object> then you get raster fallback for free*:

<object data="your.svg" type="image/svg+xml">
<img src="yourfallback.jpg" />
</object>

*) Well, not quite for free, because some browsers download both resources, see Larry's suggestion below for how to get around that.

2014 update:

  • If you want a non-interactive svg, use <img> with script fallbacks
    to png version (for older IE and android < 3). One clean and simple
    way to do that:

    <img src="your.svg" onerror="this.src='your.png'">.

    This will behave much like a GIF image, and if your browser supports declarative animations (SMIL) then those will play.

  • If you want an interactive svg, use either <iframe> or <object>.

  • If you need to provide older browsers the ability to use an svg plugin, then use <embed>.

  • For svg in css background-image and similar properties, modernizr is one choice for switching to fallback images, another is depending on multiple backgrounds to do it automatically:

    div {
    background-image: url(fallback.png);
    background-image: url(your.svg), none;
    }

    Note: the multiple backgrounds strategy doesn't work on Android 2.3 because it supports multiple backgrounds but not svg.

An additional good read is this blogpost on svg fallbacks.

SVG sprite in external file

Try this:

Create an SVG file, sprites.svg

Place the following in it:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path id="icon-home" class="path1" d="M32 18.451l-16-12.42-16 12.42v-5.064l16-12.42 16 12.42zM28 18v12h-8v-8h-8v8h-8v-12l12-9z" />
<path id="icon-camera" class="path1" d="M9.5 19c0 3.59 2.91 6.5 6.5 6.5s6.5-2.91 6.5-6.5-2.91-6.5-6.5-6.5-6.5 2.91-6.5 6.5zM30 8h-7c-0.5-2-1-4-3-4h-8c-2 0-2.5 2-3 4h-7c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h28c1.1 0 2-0.9 2-2v-18c0-1.1-0.9-2-2-2zM16 27.875c-4.902 0-8.875-3.973-8.875-8.875 0-4.902 3.973-8.875 8.875-8.875 4.902 0 8.875 3.973 8.875 8.875 0 4.902-3.973 8.875-8.875 8.875zM30 14h-4v-2h4v2z" />
</svg>

Then whenever you want to include in a use element.

<svg class="icon" viewBox="0 0 32 32">
<use xlink:href="sprites.svg#icon-home" />
</svg>

(At this time, Internet Explorer has a problem with this. IE would need a different approach. If you want, I can also show what's necessary for IE)

EDIT - Cross-browser support: Place SVG sprite elements in an XML file and call them into a defs element.

XML file, named sprites.xml:

<?xml version="1.0" encoding="UTF-8"?>
<SPRITES xmlns="http://www.w3.org/2000/svg">
<path id="iconHome" d="M32 18.451l-16-12.42-16 12.42v-5.064l16-12.42 16 12.42zM28 18v12h-8v-8h-8v8h-8v-12l12-9z" />
<path id="iconCamera" d="M9.5 19c0 3.59 2.91 6.5 6.5 6.5s6.5-2.91 6.5-6.5-2.91-6.5-6.5-6.5-6.5 2.91-6.5 6.5zM30 8h-7c-0.5-2-1-4-3-4h-8c-2 0-2.5 2-3 4h-7c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h28c1.1 0 2-0.9 2-2v-18c0-1.1-0.9-2-2-2zM16 27.875c-4.902 0-8.875-3.973-8.875-8.875 0-4.902 3.973-8.875 8.875-8.875 4.902 0 8.875 3.973 8.875 8.875 0 4.902-3.973 8.875-8.875 8.875zM30 14h-4v-2h4v2z" />
</SPRITES>

An example HTML file with Javascript to propagate the defs element.

<!DOCTYPE HTML>
<html>
<head>
<title>Sprites</title>
</head>
<body onLoad=loadSprites()>
<svg id=mySVG width="400" height="400">
<defs id="spriteDefs" />
<use xlink:href="#iconHome" transform="translate(100 100)" />
<use xlink:href="#iconHome" transform="translate(200 100)" />
<use xlink:href="#iconHome" transform="translate(300 100)" />
<use xlink:href="#iconCamera" transform="translate(100 200)" />
<use xlink:href="#iconCamera" transform="translate(200 200)" />
<use xlink:href="#iconCamera" transform="translate(300 200)" />
<use xlink:href="#iconHome" transform="translate(200 300)" />
</svg>
<script>
function loadSprites()
{
var xmlFile="sprites.xml"
var loadXML = new XMLHttpRequest;
loadXML.onload = callback;
loadXML.open("GET", xmlFile, true);
loadXML.send();
function callback()
{
//---responseText---
var xmlString=loadXML.responseText
//---DOMParser---
var parser = new DOMParser();
var mySpritesDoc=parser.parseFromString(xmlString,"text/xml").documentElement ;
var addSprites=mySpritesDoc.childNodes
for(var k=0;k<addSprites.length;k++)
{
var sprite=addSprites.item(k).cloneNode(true)
document.getElementById("spriteDefs").appendChild(sprite)
}
}
}
</script>
</body>
</html>

How to use SVG Sprite Sheet as CSS background-image while maintaining aspect ratio and scalability

Basically, I want to know if there's an easier way to define the cells in the spritesheet and simplify the CSS I use to tell each div which icon to display from the spritesheet.

No, you can't do it easier.

Try this article

Then, there's the problem of scaling. With this setup, the SVG scales to the appropriate size to be drawn on-screen, but if I decide to zoom using my browser's zoom, it pixelates. This is not how SVG is supposed to work.

In Chromium 18 it looks pretty fine - no pixelations at all.

In my test browsers list (FF3.6 Opera 9.2 IE6) I didn't see what I saw in Chromium

And about IE9, maybe problem in engine



Related Topics



Leave a reply



Submit