26

I'm looking to use SVG versions of a company logo on a website. At present, all current versions of major browsers (IE, Safari, Chrome, Firefox, Opera) support SVG, so this doesn't seem crazy. However, old browsers are still out there, so I need to fall back to PNG support.

The obvious solution is to put the SVG content in an object tag like so (forgive the inline styles...):

<object data='logo.svg' style='height:3em' >
    <img src='logo.png' style='height:3em' />
</object>

Which in theory should render the object if possible, or else render the img. However, Chrome doesn't like this and applies the height style to the object itself but not the SVG, so I end up with a little iframe-like box with scrollbars, showing a huge logo.

Another solution would be to use the PNG as the img source, and then swap it out at render time with the SVG source with javascript, if I think I'm running on a SVG-capable browser. This is not ideal because the PNG will still get downloaded, and I'm not confidant I can properly detect SVG support. Unfortunately, jQuery doesn't seem to have a SVG-detect feature.

Finally, since my website is deployed with ASP.NET, I could inspect the user agent string before serving the page, and specify the img source depending on whether I think it will support SVG. But this also has the potential problem that I am not confidant I can make the right call.

What is the preferred way of doing SVG for images?

Jon Galloway
  • 52,327
  • 25
  • 125
  • 193
Hank
  • 8,289
  • 12
  • 47
  • 57

6 Answers6

14

This is an old question, but here is another solution:

  1. Download a version of Modernizr that is trimmed down to just testing SVG (assuming that’s the only test you need).

  2. Run the test. If it passes, put in the SVG. If it fails, put in the bitmap. Essentially:

    if (!Modernizr.svg) { 
        $("#logo").css("background-image", "url(fallback.png)"); 
    }
    

SVG is a perfect use case for Modernizr, because there is no simple native way to provide a fallback.

Note: The browser don't load both (png and svg) versions.

For the record: the only reason you would need a fallback for SVG these days if you have to support IE 8 and down, or older Android.

Tomas Ramirez Sarduy
  • 17,294
  • 8
  • 69
  • 85
  • How would you deal with no js? – digout Mar 01 '13 at 03:08
  • 1
    Without javascript you would have to set up your ASP to deliver a different page or html snippet based on detected browser. That would complicate your templates, so I agree and suggest to use Modernizr. – Design by Adrian Jun 02 '13 at 15:51
  • Assuming one only needs Modernizr for SVG testing, how big will it be for the end user to download? – kleinfreund Jan 22 '14 at 16:43
  • @kleinfreund: If you only need Modernizr for test SVG support, then you could use one of this scripts from [CSS Tricks](http://css-tricks.com/test-support-svg-img/) – Tomas Ramirez Sarduy Jul 24 '14 at 08:36
4

I wouldn't call it the preferred way, but if you want to pursue your second option this should detect SVG support (from Raphaël 1.5.2):

if(window.SVGAngle || 
    document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") {
    // supports SVG
else {
    // no SVG
}

Raphaël uses this to determine if it should render using VML (IE) or SVG (everyone else).

Out of curiosity, why SVG for your logo? If you already have a PNG version, this seems like a lot of work.

Corbin March
  • 25,526
  • 6
  • 73
  • 100
  • This seems like it would help with the feature detection, but would still happen too late to avoid a PNG download. I'm interested in using SVG because the logo is well-suited for vector graphics, the SVG is about 1/3 the size of the PNG, and will better support page zooming (e.g. on mobile devices), printing, guaranteed color parity with the CSS styles, ease of future redesigns, etc... Plus I get a sense of purity out of knowing that my site has no bitmaps. Is there any reason I *shouldn't* use it wherever possible? – Hank Apr 04 '11 at 15:35
  • @Henry Jackson - I'm lazy, so I'm probably not the best person to answer _should_ or _shouldn't_. As a lazy person, I would opt for the code-free, dead-simple solution unless the alternative's bandwidth and purity benefits were huge, but that's just me. If you're comfortable with a JavaScript solution, you can test for SVG support and then inject the appropriate element (SVG or PNG) into the DOM. That should avoid the automatic PNG download when it's not needed. – Corbin March Apr 04 '11 at 15:53
3

To solve your problem w/resizing SVGs in the object tag:

Add "preserveAspectRatio" and "viewBox" attributes to the svg tag. Open the file in a text editor and find the tag. in that tag, add the following attributes:

preserveAspectRatio="xMinYMin meet" viewBox="0 0 {width} {height}"

Replace {width} and {height} with some defaults for the viewBox. I use the values from the "width" and "height" attributes of the SVG tag. Save the SVG and it should now scale as expected.

See: How do I scale a stubborn SVG embedded with the <object> tag?

The problem w/SVGs in the object tag, though is that they swallow the clicks.

SVG as background-image w/PNG fallback: http://www.broken-links.com/2010/06/14/using-svg-in-backgrounds-with-png-fallback/

My favorite is using the img tag and an onerror handler to change the src tag to a PNG.

Another good resource: http://www.schepers.cc/svg/blendups/embedding.html

Community
  • 1
  • 1
bogeylicious
  • 5,071
  • 3
  • 25
  • 17
3

The only thing you need is CSS. First you declare the fallback image as a background-image. Then you can use multiple backgrounds to add the SVG.

IE8 and below will ignore the second background-image-declaration, because the lacking support of multiple backgrounds.

By the way, I'm using the img element here, because a logo is content, not layout. Using background-images might appear to be wrong in this context, but I disagree. You get the best of the worlds: SVG logo, fallback for

HTML:

<a href="/" class="site-logo">
    <!-- base64 encoded 1x1 px big transparent gif -->
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="company logo">
</a>

CSS (using multiple background images):

caniuse: multiple backgrounds

  • PNG for IE <9, FF <3.6, Opera <10.5
  • SVG for all the others supporting SVG
  • Android 2.x won't have a PNG or SVG, due to these versions actually supporting multiple backgrounds, but not SVG
  • There is only one HTTP request made for browsers supporting SVG
.site-logo > img {
    /* Dimensions of your image need to be set */
    width: 32px;
    height: 32px;

    /* Fallback for <IE9 */
    background-image: url(logo.png);

    /* multiple backgrounds are ignored by <IE9 */
    background-image: url(logo.svg), none;
}

CSS (using linear gradients):

caniuse: CSS gradients

  • PNG for IE <10, FF <3.6, Safari <4.0, Opera <11.1, Opera Mini, Opera Mobile <11.1
  • SVG for all the others supporting SVG (if vendor-prefixes are specified)
  • Ignoring the old gradient syntax for webkit makes Android 2.x use the PNG fallback
.site-logo > img {
    /* Dimensions of your image need to be set */
    width: 32px;
    height: 32px;

    background: transparent url(logo.png) center center no-repeat;
    background-image: -webkit-linear-gradient(transparent, transparent), url(logo.svg);
    background-image:         linear-gradient(transparent, transparent), url(logo.svg);
}
kleinfreund
  • 6,546
  • 4
  • 30
  • 60
  • Using linear-gradient(transparent, transparent) instead of multiple backgrounds seems like a better method, see http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique – Patrick Fabrizius Jan 30 '14 at 10:52
  • @PatrickFabrizius Why is this method better than using multiple backgrounds? The technique is basically the same. – kleinfreund Jan 30 '14 at 15:28
  • It provides a fallback for Android 2.x which multiple backgrounds alone apparently does not. – Patrick Fabrizius Jan 30 '14 at 16:50
  • @PatrickFabrizius Android 2.x has support for multiple backgrounds as well: [browser support](http://caniuse.com/multibackgrounds). Linear-gradients are even worse, because they need the `-webkit-` vendor prefix. – kleinfreund Jan 30 '14 at 16:57
  • Thats the problem. Multiple background support makes Android 2.x load the SVG when it should not. With -webkit-linear-gradient Android 2.x will instead load the fallback. – Patrick Fabrizius Jan 30 '14 at 17:14
  • @PatrickFabrizius How? Android 2.x has no support for SVG at all. It will ignore this rule alltogether. – kleinfreund Jan 30 '14 at 17:24
  • Correct, Android 2.x has no support for SVG, but supports multiple backgrounds. Thus, it will respond to the second statement (with multiple backgrounds) and ignore the fallback, instead trying to use the SVG. This will fail. However, Android 2.x does not support linear gradient, therefore it will ignore the second statement and use the PNG. – Patrick Fabrizius Jan 30 '14 at 22:45
  • @PatrickFabrizius This also correct, but only if one doesn't specify the `-webkit-` vendor prefix. However if he does, he won't have SVG for Android +3 and iOS <7. – kleinfreund Jan 31 '14 at 12:45
  • 2
    The pros of your method is that it displays the SVG instead of the PNG on IOS3-4, IE9, and FF4-15, the cons are that it displays an empty/broken image in Android 2.x, IE6-7 and FF3.6 or less. Both our methods displays the SVG on all other tested devices/browsers (even IOS5-7 contrary to what you suggest). IMHO, a method which provides an image 100% of the time is better than one that displays an empty background in some cases. – Patrick Fabrizius Feb 01 '14 at 19:44
  • @PatrickFabrizius I was talking about ignoring prefixes at all. I've added the linear-gradient technique. I'd rather drop the old droids for having more SVG support. – kleinfreund Feb 01 '14 at 20:07
1

The best method I have found including SVG as an HTML element (with fallback) is this one:

<svg preserveAspectRatio="xMidYMid meet" viewBox="0 0 100 100" style="width: 100px; height: 100px; vertical-align: top;">
    <image xlink:href="image.svg" src="fallback.png" width="100%" height="100%"/>
</svg> 

Pros:

  • Provides fallback in every device/browser I have tested (IE6-IE11, Android 2.0+, IOS3-7)
  • Only one image is loaded for each tested browser (except IE9-IE11)
  • Externally loaded images allows image to be cached

Cons:

  • Unable to use as scaleable (responsive) image in IE9-IE11 (see this question)
  • IE9-IE11 loads both images
  • IOS3-4 (Mobile Safari) has SVG support but displays the PNG (since it lacks inline SVG support)
  • SVG file must not have height / width attributes (unsure about this, but have read about it somewhere and in my tests my SVG did not have them anyway)
  • Does not validate

Please provide comments with additional pros / cons you can think of. I know for one SVG's can appear pixeled in some browsers, but I was unable to test zooming in since using browserstack for emulation.

Source: http://lynn.ru/examples/svg/en.html

Community
  • 1
  • 1
1

Try svg-web they have a number of different ways of displaying svg images including flash with automatic fallback.

babsher
  • 1,016
  • 2
  • 8
  • 11