Should I use ,
, or
for loading SVG files into a page in a way similar to loading a
jpg
Found one solution with pure CSS and without double image downloading. It is not beautiful as I want, but it works.
<!DOCTYPE html>
<html>
<head>
<title>HTML5 SVG demo</title>
<style type="text/css">
.nicolas_cage {
background: url('nicolas_cage.jpg');
width: 20px;
height: 15px;
}
.fallback {
}
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
<style>
<![CDATA[
.fallback { background: none; background-image: none; display: none; }
]]>
</style>
</svg>
<!-- inline svg -->
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40">
<switch>
<circle cx="20" cy="20" r="18" stroke="grey" stroke-width="2" fill="#99FF66" />
<foreignObject>
<div class="nicolas_cage fallback"></div>
</foreignObject>
</switch>
</svg>
<hr/>
<!-- external svg -->
<object type="image/svg+xml" data="circle_orange.svg">
<div class="nicolas_cage fallback"></div>
</object>
</body>
</html>
The idea is to insert special SVG with fallback style.
More details and testing process you can find in my blog.
This jQuery function captures all errors in svg images and replaces the file extension with an alternate extension
Please open the console to see the error loading image svg
(function($){
$('img').on('error', function(){
var image = $(this).attr('src');
if ( /(\.svg)$/i.test( image )) {
$(this).attr('src', image.replace('.svg', '.png'));
}
})
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="https://jsfiddle.net/img/logo.svg">
If you need your SVGs to be fully styleable with CSS they have to be inline in the DOM. This can be achieved through SVG injection, which uses Javascript to replace a HTML element (usually an <img>
element) with the contents of an SVG file after the page has loaded.
Here is a minimal example using SVGInject:
<html>
<head>
<script src="svg-inject.min.js"></script>
</head>
<body>
<img src="image.svg" onload="SVGInject(this)" />
</body>
</html>
After the image is loaded the onload="SVGInject(this)
will trigger the injection and the <img>
element will be replaced by the contents of the file provided in the src
attribute. This works with all browsers that support SVG.
Disclaimer: I am the co-author of SVGInject
In most circumstances, I recommend using the <object>
tag to display SVG images. It feels a little unnatural, but it's the most reliable method if you want to provide dynamic effects.
For images without interaction, the <img>
tag or a CSS background can be used.
Inline SVGs or iframes are possible options for some projects, but it's best to avoid <embed>
But if you want to play with SVG stuff like
Go with the embedded one
<svg>
<g>
<path> </path>
</g>
</svg>
An easy alternative that works for me is to insert the svg code into a div. This simple example uses javascript to manipulate the div innerHTML.
svg = '<svg height=150>';
svg+= '<rect height=100% fill=green /><circle cx=150 cy=75 r=60 fill=yellow />';
svg+= '<text x=150 y=95 font-size=60 text-anchor=middle fill=red>IIIIIII</text></svg>';
document.all.d1.innerHTML=svg;
<div id='d1' style="float:right;"></div><hr>
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.