11

I'm looking for a way to have older browsers display a PNG image in place of an SVG as a fallback when detected. The logo for my site is currently in SVG but older browsers, specifically IE 8 and below won't render it. I already have the logo in PNG. What's the best way to execute this?

Thanks

Charlie
  • 219
  • 1
  • 4
  • 6

8 Answers8

17

Use HTML conditional comments.

<!--[if lte IE 8]><img src="logo.png" /><![endif]-->
<!--[if gt IE 8]><img src="logo.svg" /><![endif]-->
<!--[if !IE]> --><img src="logo.svg" /><!-- <![endif]-->

http://msdn.microsoft.com/en-us/library/ms537512%28v=vs.85%29.aspx

If you're also looking for a way to handle this for browsers other than IE, you should check the user agent with javascript or php.

Rick Kuipers
  • 6,616
  • 2
  • 17
  • 37
  • Thanks, that worked perfectly. Only one issue remains now which I imagine can be resolved easily with the right code. In IE 8 and below, the PNG displays fine but the grey outline and red X icon from IE not knowing what to do with the SVG still remains. Is there a way to have IE ignore my SVG IMG tag? Thanks. – Charlie Jan 20 '12 at 20:07
  • That's why you would have to put all three conditional comments in there. IE will not see the .svg if it's inside a – Rick Kuipers Jan 20 '12 at 20:15
  • I just tried using all three conditional comments as listed there but only IE browsers render the logo. It doesn't show up at all in Firefox, Chrome or any other non-IE browser I tested it in. – Charlie Jan 20 '12 at 20:36
  • Sorry, appearently the if !IE one has a different syntax. I edited my post above, it should work now (tested). – Rick Kuipers Jan 20 '12 at 21:07
  • `` will also work for IE 9+ and non-IE browsers without duplicating the tag. – mcrumley Jul 26 '14 at 19:54
  • Conditional comments are no longer supported in standards mode in IE 10 and later. – quant_dev Apr 27 '18 at 21:35
5
<object type="image/svg+xml" data="image.svg">
    <img src="image.png" alt="image"/>
</object>
Spadar Shut
  • 15,111
  • 5
  • 47
  • 54
  • 2
    A slight disadvantage is that browsers typically download both resources in this case. – Erik Dahlström Jan 23 '12 at 09:26
  • Another disadvantage is that the "object" element may have some weird event behavior, e.g. jQuery UI tooltips attached to the "object" will open but not close on mouse out in many browsers. – hmundt Sep 11 '15 at 11:29
3

I use the "transparent gradient" technique because is CSS-only and does not require browser-specific hacks.

The technique is based on the fact that browsers capable of using CSS gradients are modern enough to support SVG rendering. So, if we use a background image that is composed of two layers, one being the SVG and the other being a gradient, only those browsers capable of understanding the gradient syntax will try to display the SVG.

The following code shows the basic CSS rules:

background: transparent url(fallback-image.png) center center no-repeat;
background-image: -webkit-linear-gradient(transparent, transparent), url(vector-image.svg);
background-image: -moz-linear-gradient(transparent, transparent), url(vector-image.svg);
background-image: linear-gradient(transparent, transparent), url(vector-image.svg);

With this technique, all users will see the image and it will be displayed using SVG for the latest browser versions. The price to pay is that some old browser versions (such as IE9 or Firefox 3.5) that are also capable of rendering SVG but do not support gradients will display the fallback version.

Pau Giner
  • 1,282
  • 11
  • 11
2

How about this?

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

Also take a look at SVGeezy.

SepehrM
  • 1,087
  • 2
  • 20
  • 44
  • This loads the svg in all cases. It could also introduce an endless loop if the onerror image causes an error. – Nemo64 May 04 '15 at 10:09
  • @Nemo64 This replaces the svg if it can't be loaded. Most browsers check `onerror` only once (such as Chrome & FF 15+). For more info about Firefox refer to https://bugzilla.mozilla.org/show_bug.cgi?id=528448 For backward compatibility you could simply add `this.onerror=null;` before settings `src`. – SepehrM May 04 '15 at 14:19
  • @Nemo64 Although nowadays I recommend SVGeezy over this approach, many popular web sites are still using this one. – SepehrM May 04 '15 at 14:21
2

I suggest rewriting the src attribute of your SVG images when you detect (via Modernizr or similar) that the browser doesn't support SVG natively. Something like:

if (!Modernizr.svg) {
    var imgs = document.getElementsByTagName('img');
    var endsWithDotSvg = /.*\.svg$/
    var i=0;
    var l = imgs.length;
    for (; i != l; ++i) {
        if (imgs[i].src.match(endsWithDotSvg)) {
            imgs[i].src = imgs[i].src.slice(0, -3) + "png";
        }
    }
}
adiabatic
  • 398
  • 2
  • 10
0

To follow up on Adiabatic's comment: You could also set the fallback img path as data-attribute. This allows for more flexibility in your fallback paths.

Example (HTML +JS):

<object type="image/svg+xml" data="image.svg" data-fallback="image.png"></object>

<script>
if (!Modernizr.svg) {
    var imgs = document.getElementsByTagName('img');
    var endsWithDotSvg = /.*\.svg$/
    var i=0;
    var l = imgs.length;
    for (; i != l; ++i) {
        if (imgs[i].src.match(endsWithDotSvg)) {
           var fallback = imgs[i].getAttribute('data-fallback');
           if(typeof fallback !== "undefined" && fallback !== "")
           {
               imgs[i].src = fallback;
           }
        }
    }
}
</script>
nicoes
  • 83
  • 1
  • 8
0

I prefer the "conditional comments SVG fallback technique" for content images, as described by David Goss, if the images are no decoration.

HTML:

<a class="site-logo" href="/">
    <!--[if gte IE 9]><!--><img alt="Acme Supplies" src="logo.svg" data-fallback="logo.png" onerror="this.src=this.getAttribute('data-fallback');this.onerror=null;" /><!--<![endif]-->
    <!--[if lt IE 9]><img alt="Acme Supplies" src="logo.png" /><![endif]-->
</a>

http://davidgoss.co.uk/2013/01/30/use-svg-for-your-logo-and-still-support-old-ie-and-android/

For decorational images, I use the "transparent gradient SVG fallback technique", as described by Pau Giner.

CSS:

.icon-file {
    background: transparent url(../images/file.png) center center no-repeat;
    background-image: -webkit-linear-gradient(transparent,transparent), url(../images-svg/file.svg);
    background-image:      -o-linear-gradient(transparent,transparent), url(../images-svg/file.svg);
    background-image:    -moz-linear-gradient(transparent,transparent), url(../images-svg/file.svg);
    background-image:     -ms-linear-gradient(transparent,transparent), url(../images-svg/file.svg);
    background-image:         linear-gradient(transparent,transparent), url(../images-svg/file.svg);
    background-size: 100%;
}

http://pauginer.com/post/36614680636/invisible-gradient-technique

hmundt
  • 545
  • 3
  • 9
-2

This method worked for me:

<?php
$browser = get_browser(null, true);
$extension = "png";

if ($browser['browser'] == "Chrome" && $browser['version'] >= 49){
    $extension = "svg";
}else if($browser['browser'] == "Firefox" && $browser['version'] >= 57){
    $extension = "svg";
}else if($browser['browser'] == "Opera" && $browser['version'] >= 49){
    $extension = "svg";
}else if($browser['browser'] == "IE" && $browser['version'] >= 11){
    $extension = "svg";
}else if($browser['browser'] == "Safari" && $browser['version'] >= 11){
    $extension = "svg";

}
?>

By defect you are telling the variable"$extension" to be PNG, but if the browser version is capable of rendering SVG, then the variable will change to SVG.

Then in your HTML you just complete the file extension making an echo of the variable.

<img src="image.<?php echo $extension ?>">

Now your web page will load "image.png" or "image.svg" depending on browser version.

Important information:

** in order to make this script work you need to set up the file browscap.ini so you can use the PHP function "get_browser".

** Browser capabilities regarding SVG were obtained from this website:

https://caniuse.com/#search=svg

  • All modern browsers have supported SVG for years. Click on the show all button on the caniuse page to see how far back support goes. This answer might have been useful 5 years ago, today it's completely pointless and also incorrect as something like Firefox ESR supports SVG perfectly fine and yet you'd exclude it using your tests. – Robert Longson Feb 19 '18 at 21:43
  • Well... depending on your location, the number of people who DO NOT use modern browsers can vary a lot. In my environment at least this script is not pointless and it does help me with my projects.... In the other hand, the fact that I did not include Firefox ESR, does not make the answer incorrect, you just need to add that specific browser version to the script. – user289877 Feb 20 '18 at 11:42