在旧浏览器中显示PNG替代SVG的条件代码是什么?

11

我正在寻找一种方法,在检测到的情况下让旧版浏览器显示PNG图像作为SVG的替代。我的网站徽标目前是SVG格式,但旧版浏览器(特别是IE 8及以下版本)无法渲染它。我已经有了PNG格式的徽标。执行这个任务的最佳方法是什么?

谢谢。


新解决方案在https://dev59.com/TG855IYBdhLWcg3wNhZ1#26577458。 - Artur A
8个回答

17
使用HTML条件注释。
<!--[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

如果您还想处理非IE浏览器的情况,您可以使用JavaScript或PHP检查用户代理。

谢谢,那个完美地解决了问题。现在只剩下一个问题,我想用正确的代码很容易就能解决。在IE 8及以下版本中,PNG显示正常,但是由于IE不知道如何处理SVG,灰色轮廓和红色X图标仍然存在。有没有办法让IE忽略我的SVG IMG标签?谢谢。 - Charlie
这就是为什么你必须把所有三个条件注释都放在里面的原因。 如果 .svg 在 <!--[if !IE]> 标签内部,那么 IE 就看不到它,因为该标签只能被非 Internet Explorer 浏览器看到。 - Rick Kuipers
我刚刚尝试了那里列出的所有三个条件注释,但只有IE浏览器可以渲染标志。在我测试的Firefox、Chrome或任何非IE浏览器中都无法显示。 - Charlie
抱歉,显然 if !IE 的语法不同。我已经编辑了我的帖子,现在应该可以工作了(已测试)。 - Rick Kuipers
<!--[if gte IE 9]><!--><img src="logo.svg" /><!--<![endif]--> 这段代码可以在IE 9及以上版本和非IE浏览器中正常工作,而不会重复使用<svg>标签。 - mcrumley
在IE 10及更高版本的标准模式下不再支持条件注释。 - quant_dev

5
<object type="image/svg+xml" data="image.svg">
    <img src="image.png" alt="image"/>
</object>

2
一个小缺点是,在这种情况下,浏览器通常会下载两个资源。 - Erik Dahlström
另一个缺点是,“object”元素可能具有一些奇怪的事件行为,例如,在许多浏览器中,附加到“object”的jQuery UI工具提示将在鼠标移出时打开但不关闭。 - hmundt

3
我使用“透明渐变”技术,因为它只需CSS即可实现,不需要针对特定浏览器的hack。
该技术基于一个事实:支持CSS渐变的浏览器已经足够现代,可以支持SVG渲染。因此,如果我们使用一个由两个图层组成的背景图片,其中一个是SVG,另一个是渐变,那么只有那些理解渐变语法的浏览器才会尝试显示SVG。
以下代码展示了基本的CSS规则:
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);

使用这种技术,所有用户都将看到该图像,并且它将在最新的浏览器版本中使用SVG进行显示。付出的代价是一些旧的浏览器版本(例如IE9或Firefox 3.5)虽然也能呈现SVG但不支持渐变,将显示备用版本。

2
我建议在检测到浏览器不支持SVG本地化时(通过Modernizr或类似工具),重写SVG图像的src属性。例如:
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";
        }
    }
}

2
这个怎么样?
<img src="your.svg" onerror="this.src=your.png">  

还可以看看SVGeezy


这将在所有情况下加载svg。如果onerror图像引起错误,它也可能引入无限循环。 - Nemo64
@Nemo64 如果无法加载svg,这将替换它。大多数浏览器只在第一次检查onerror(例如Chrome和FF 15+)。有关Firefox的更多信息,请参阅https://bugzilla.mozilla.org/show_bug.cgi?id=528448 为了向后兼容,您可以在设置src之前简单地添加this.onerror=null; - SepehrM
虽然现在我建议使用SVGeezy而不是这种方法,但许多流行的网站仍在使用它。 - SepehrM

0

回复Adiabatic的评论:

您还可以将备用img路径设置为data属性。这样可以使备用路径更加灵活。

示例(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>

0
我更喜欢使用 David Goss 描述的“条件注释 SVG 回退技术”来处理内容图像,如果这些图像不是装饰性的。
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/

对于装饰性图片,我使用Pau Giner所描述的“透明渐变SVG回退技术”。

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


-2

这个方法对我有效:

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

}
?>

默认情况下,您正在告诉变量"$extension"为PNG格式,但如果浏览器版本能够呈现SVG格式,则该变量将更改为SVG格式。

然后在您的HTML中,只需完成文件扩展名并回显该变量即可。

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

现在您的网页将根据浏览器版本加载"image.png"或"image.svg"。

重要信息:

** 为了使此脚本正常工作,您需要设置文件browscap.ini,以便使用PHP函数“get_browser”。

** 关于SVG的浏览器功能是从此网站获取的:

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


所有现代浏览器多年来都支持SVG。单击caniuse页面上的“显示全部”按钮,以查看支持的历史版本。这个答案在5年前可能有用,但今天它完全没有意义,而且也是不正确的,因为像Firefox ESR这样的浏览器完全支持SVG,但您使用测试会将其排除在外。 - Robert Longson
嗯...根据您所在的位置,不使用现代浏览器的人数可能会有很大差异。至少在我的环境中,这个脚本是有用的,并且确实帮助了我完成项目...另一方面,我没有包括Firefox ESR并不意味着答案是错误的,您只需要将该特定浏览器版本添加到脚本中即可。 - user289877

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接