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

HtmlSvgVector Graphics

Html Problem Overview


Should I use <img>, <object>, or <embed> for loading SVG files into a page in a way similar to loading a jpg, gif or png?

What is the code for each to ensure it works as well as possible? (I'm seeing references to including the mimetype or pointing to fallback SVG renderers in my research and not seeing a good state of the art reference).

Assume I am checking for SVG support with Modernizr and falling back (probably doing a replacement with a plain <img> tag)for non SVG-capable browsers.

Html Solutions


Solution 1 - Html

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.

Solution 2 - Html

From IE9 and above you can use SVG in a ordinary IMG tag..

https://caniuse.com/svg-img

<img src="/static/image.svg">

Solution 3 - Html

<object> and <embed> have an interesting property: they make it possible to obtain a reference to SVG document from outer document (taking same-origin policy into account). The reference can then be used to animate the SVG, change its stylesheets, etc.

Given

<object id="svg1" data="/static/image.svg" type="image/svg+xml"></object>

You can then do things like

document.getElementById("svg1").addEventListener("load", function() {
    var doc = this.getSVGDocument();
    var rect = doc.querySelector("rect"); // suppose our image contains a <rect>
    rect.setAttribute("fill", "green");
});

Solution 4 - Html

Use srcset

Most current browsers today support the srcset attribute, which allows specifying different images to different users. For example, you can use it for 1x and 2x pixel density, and the browser will select the correct file.

In this case, if you specify an SVG in the srcset and the browser doesn't support it, it'll fallback on the src.

<img src="logo.png" srcset="logo.svg" alt="My logo">

This method has several benefits over other solutions:

  1. It's not relying on any weird hacks or scripts
  2. It's simple
  3. You can still include alt text
  4. Browsers that support srcset should know how to handle it so that it only downloads the file it needs.

Solution 5 - Html

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

Solution 6 - Html

The best option is to use SVG Images on different devices :)

<img src="your-svg-image.svg" alt="Your Logo Alt" onerror="this.src='your-alternative-image.png'">

Solution 7 - Html

I would personally use an <svg> tag because if you do you have full control over it. If you do use it in <img> you don't get to control the innards of the SVG with CSS etc.

another thing is browser support.

Just open your svg file and paste it straight into the template.

<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3400 2700" preserveAspectRatio="xMidYMid meet" (click)="goHome();">
  <g id="layer101">
    <path d="M1410 2283 c-162 -225 -328 -455 -370 -513 -422 -579 -473 -654 -486 -715 -7 -33 -50 -247 -94 -475 -44 -228 -88 -448 -96 -488 -9 -40 -14 -75 -11 -78 2 -3 87 85 188 196 165 180 189 202 231 215 25 7 129 34 230 60 100 26 184 48 185 49 4 4 43 197 43 212 0 10 -7 13 -22 9 -13 -3 -106 -25 -208 -49 -102 -25 -201 -47 -221 -51 l-37 -7 8 42 c4 23 12 45 16 49 5 4 114 32 243 62 129 30 240 59 246 66 10 10 30 132 22 139 -1 2 -110 -24 -241 -57 -131 -33 -240 -58 -242 -56 -6 6 13 98 22 107 5 4 135 40 289 80 239 61 284 75 307 98 14 15 83 90 153 167 70 77 132 140 139 140 7 0 70 -63 141 -140 70 -77 137 -150 150 -163 17 -19 81 -39 310 -97 159 -41 292 -78 296 -82 8 -9 29 -106 24 -111 -1 -2 -112 24 -245 58 -134 33 -245 58 -248 56 -6 -7 16 -128 25 -136 5 -4 112 -30 238 -59 127 -29 237 -54 246 -57 11 -3 20 -23 27 -57 6 -28 9 -53 8 -54 -1 -1 -38 7 -81 17 -274 66 -379 90 -395 90 -16 0 -16 -6 3 -102 11 -57 21 -104 22 -106 1 -1 96 -27 211 -57 115 -31 220 -60 234 -66 14 -6 104 -101 200 -211 95 -111 175 -197 177 -192 1 5 -40 249 -91 542 l-94 532 -145 203 c-220 309 -446 627 -732 1030 -143 201 -265 366 -271 367 -6 0 -143 -183 -304 -407z m10 -819 l-91 -161 -209 -52 c-115 -29 -214 -51 -219 -49 -6 1 32 55 84 118 l95 115 213 101 c116 55 213 98 215 94 1 -3 -38 -78 -88 -166z m691 77 l214 -99 102 -123 c56 -68 100 -125 99 -127 -4 -3 -435 106 -447 114 -4 2 -37 59 -74 126 -38 68 -79 142 -93 166 -13 23 -22 42 -20 42 2 0 101 -44 219 -99z"/>
    <path d="M1126 2474 c-198 -79 -361 -146 -363 -147 -2 -3 -70 -410 -133 -805 -12 -73 -20 -137 -18 -143 2 -6 26 23 54 63 27 40 224 320 437 622 213 302 386 550 385 551 -2 2 -165 -62 -362 -141z"/>
    <path d="M1982 2549 c25 -35 159 -230 298 -434 139 -203 283 -413 319 -465 37 -52 93 -134 125 -182 59 -87 83 -109 73 -65 -5 20 -50 263 -138 747 -17 91 -36 170 -42 176 -9 8 -571 246 -661 280 -14 6 -7 -10 26 -57z"/>
    <path d="M1679 1291 c-8 -11 -71 -80 -141 -153 l-127 -134 -95 -439 c-52 -242 -92 -442 -90 -445 6 -5 38 28 218 223 l99 107 154 0 c85 0 163 -4 173 -10 10 -5 78 -79 151 -162 73 -84 136 -157 140 -162 18 -21 18 4 -2 85 -11 46 -58 248 -105 448 l-84 364 -87 96 c-108 121 -183 201 -187 201 -2 0 -10 -9 -17 -19z m96 -488 c33 -102 59 -189 57 -192 -2 -6 -244 -2 -251 4 -5 6 120 375 127 375 4 0 34 -84 67 -187z"/>
    </g>
  </svg>

then in your css you can simply eg:

svg {
  fill: red;
}

Some resource: SVG tips

Solution 8 - Html

If you use <img> tags, then webkit based browsers won't display embedded bitmapped images.

For any kind of advanced SVG use, including the SVG inline offers by far the most flexibility.

Internet Explorer and Edge will resize the SVG correctly, but you must specify both the height and width.

You can add onclick, onmouseover, etc. inside the svg, to any shape in the SVG: onmouseover="top.myfunction(evt);"

You can also use web fonts in the SVG by including them in your regular style sheet.

Note: if you are exporting SVG's from Illustrator, the web font names will be wrong. You can correct this in your CSS and avoid messing around in the SVG. For example, Illustrator gives the wrong name to Arial, and you can fix it like this:

@font-face {    
    font-family: 'ArialMT';    
    src:    
        local('Arial'),    
        local('Arial MT'),    
        local('Arial Regular');    
    font-weight: normal;    
    font-style: normal;    
}

All this works on any browser released since 2013.

For an example, see ozake.com. The whole site is made of SVG's except for the contact form.

Warning: Web fonts are imprecisely resized in Safari — and if you have lots of transitions from plain text to bold or italic, there may be a small amount of extra or missing space at the transition points. See my answer at this question for more information.

Solution 9 - Html

My two cents: as of 2019, 93% of browsers in use (and 100% of the last two version of every one of them) can handle SVG in <img> elements:

enter image description here

Source: Can I Use

So we could say that there's no reason to use <object> anymore.

However it's still has its pros:

  • When inspecting (e.g. with Chrome Dev Tools) you are presented with the whole SVG markup in case you wanted to tamper a bit with it and see live changes.

  • It provides a very robust fallback implementation in case your browser does not support SVGs (wait, but every one of them does!) which also works if the SVG isn't found. This was a key feature of XHTML2 spec, which is like betamax or HD-DVD

But there are also cons:

Solution 10 - Html

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.

Solution 11 - Html

Even though w3schools does not recommend the <embed> tag, it was the only thing that made my svg with mixed pattern and mask working in Chrome:

<embed src="logo.svg" style="width:100%; height:180px" type="image/svg+xml" />

Whereas Firefox was fine with

<svg style="width:100%">
    <use xlink:href="logo.svg#logo"></use>
</svg>

Chrome did not render the gradient:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="146" version="1.1">
	<title>digicraft punchcard logo</title>
    <defs>
		<linearGradient id="punchcard-gradient" x1="100%" y1="50%" x2="0%" y2="50%">
			<stop offset="0%" style="stop-color:rgb(128,128,128);stop-opacity:0" />
			<stop offset="100%" style="stop-color:rgb(69,69,69);stop-opacity:1" />
		</linearGradient>
        <pattern id="punchcard-pattern-v" x="0" y="0" width="21" height="21" patternUnits="userSpaceOnUse">
        	<rect x="0" y="0" width="20" height="20" fill="skyblue" onClick="mClick(this)" />
        </pattern>
        <pattern id="punchcard-pattern-h" x="0" y="0" width="21" height="145" patternUnits="userSpaceOnUse">
        	<rect x="0" y="0" width="21" height="20" fill="skyblue" />
        	<rect x="0" y="20" width="20" height="84" fill="url(#punchcard-pattern-v)" />
        	<rect x="0" y="105" width="20" height="20" fill="skyblue" />
        	<rect x="0" y="126" width="21" height="20" fill="skyblue" />
        </pattern>
        <mask id="punchcard-mask" width="10" height="100%">
        	<rect width="100%" height="146" fill="url(#punchcard-pattern-h)" />
        </mask>
    </defs>
	    <rect x="0" y="0" width="100%" height="159" fill="url(#punchcard-gradient)" mask="url(#punchcard-mask)" />
</svg>

The same with <object> and <img> in both browsers.

Solution 12 - Html

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

  • Changing colors
  • Resize path
  • rotate svg

Go with the embedded one

<svg>
    <g> 
        <path> </path>
    </g>
</svg>

Solution 13 - Html

Based on personal experience, I suggest load svg file by src in image tag that if you have many svg icon or append dynamically on one page, it will slow down and bad performance

<img src="./file.svg"/> is better performance than 

<div><svg>.....</svg></div>

but if you want assign css style in hover you must use embed

Solution 14 - Html

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">

Solution 15 - Html

It's easier to just use the <svg> tag because your code will run faster and you are directly using your svg. To get only the svg tag copy the svg file without xml tag. The result will be something like this:

<svg fill="#000000" xmlns="http://www.w3.org/2000/svg"  viewBox="0 0 16 16" width="64px" height="64px"><path d="M 4.5 2 C 3.675781 2 3 2.675781 3 3.5 L 3 14.484375 L 8 10.820313 L 13 14.484375 L 13 3.5 C 13 2.675781 12.324219 2 11.5 2 Z M 4.5 3 L 11.5 3 C 11.78125 3 12 3.21875 12 3.5 L 12 12.515625 L 8 9.578125 L 4 12.515625 L 4 3.5 C 4 3.21875 4.21875 3 4.5 3 Z"/></svg>

Solution 16 - Html

You can insert a SVG indirectly using <img> HTML tag and this is possible on StackOverflow following what is described below:

I have following SVG file on my PC

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="350" height="350" viewBox="0 0 350 350">

  <title>SVG 3 Circles Intersection </title>

    <circle cx="110" cy="110" r="100"
            stroke="red"
            stroke-width="3"
            fill="none"
            />
    <text x="110" y="110" 
          text-anchor="middle"
          stroke="red"
          stroke-width="1px"
          > Label
    </text>
    <circle cx="240" cy="110" r="100" 
            stroke="blue" 
            stroke-width="3"
            fill="none"
            />
    <text x="240" y="110" 
          text-anchor="middle" 
          stroke="blue" 
          stroke-width="1px"
          > Ticket
    </text>
    <circle cx="170" cy="240" r="100" 
            stroke="green" 
            stroke-width="3" 
            fill="none"
            />
    <text x="170" y="240" 
          text-anchor="middle" 
          stroke="green" 
          stroke-width="1px"
          > Vecto
    </text>
</svg>

I have uploaded this image to https://svgur.com

After upload was terminated, I have obtained following URL:

https://svgshare.com/i/RJV.svg

I have then MANUALLY (without using IMAGE icon) added following html tag

<img src="https://svgshare.com/i/KJV.svg"/>

and the result is just below

https://svgshare.com/i/RJV.svg"/>

For user with some doubt, it is possible to see what I have done in editing following answer on StackOverflow inserting SVG image

REMARK-1: the SVG file must contains <?xml?> element. At begin, I have simply created a SVG file that begins directly with <svg> tag and nothing worked !

REMARK-2: at begin, I have tried to insert an image using IMAGE icon of Edit Toolbar. I paste URL of my SVG file but StackOverflow don't accept this method. The <img> tag must be added manually.

I hope that this answer can help other users.

Solution 17 - Html

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>

Solution 18 - Html

I recommend using the combination of

<svg viewBox="" width="" height="">
<path fill="#xxxxxx" d="M203.3,71.6c-.........."></path>
</svg>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionartlungView Question on Stackoverflow
Solution 1 - HtmlErik DahlströmView Answer on Stackoverflow
Solution 2 - HtmlChristian LandgrenView Answer on Stackoverflow
Solution 3 - HtmlWGHView Answer on Stackoverflow
Solution 4 - HtmlScribblemacherView Answer on Stackoverflow
Solution 5 - HtmlWaruyamaView Answer on Stackoverflow
Solution 6 - HtmlRoberth SolísView Answer on Stackoverflow
Solution 7 - HtmlLazerBananaView Answer on Stackoverflow
Solution 8 - HtmlAndrew SwiftView Answer on Stackoverflow
Solution 9 - HtmlffflabsView Answer on Stackoverflow
Solution 10 - HtmlArtur AView Answer on Stackoverflow
Solution 11 - HtmlsntrcodeView Answer on Stackoverflow
Solution 12 - HtmlHidayt RahmanView Answer on Stackoverflow
Solution 13 - HtmlMahdi PorkarView Answer on Stackoverflow
Solution 14 - HtmlAndres SeparView Answer on Stackoverflow
Solution 15 - HtmlMahdyarView Answer on Stackoverflow
Solution 16 - HtmlschlebeView Answer on Stackoverflow
Solution 17 - Htmluser3509666View Answer on Stackoverflow
Solution 18 - HtmlGrv97View Answer on Stackoverflow