我是否对SVG文件使用<img>、<Object>或<embed>?

我应该使用<img><object><embed>以类似于加载jpggifpng的方式将SVG文件加载到页面中吗?

每个代码的代码是什么,以确保它尽可能地工作?(我在我的研究中看到了包含mimetype或指向后备SVG渲染器的参考,但没有看到良好的技术参考)。

假设我正在用modnizr检查SVG支持,并在不支持SVG的浏览器中回退(可能用普通的<img>标记替换)。

817470 次浏览

我可以推荐SVG Primer(由W3C发布),它涵盖了这个主题:http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML

如果您使用<object>,那么您可以免费获得光栅回退*:

<object data="your.svg" type="image/svg+xml">
<img src="yourfallback.jpg" />
</object>

*)好吧,不是免费的,因为有些浏览器下载这两种资源,请参阅下面拉里的建议,了解如何解决这个问题。

2014年更新:

  • 如果您想要一个非交互式svg,请使用<img>和脚本回退 到png版本(适用于较旧的IE和android<3)。一个干净简单的 如何做到这一点:

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

    这将表现得很像GIF图像,如果您的浏览器支持声明性动画(SMIL),那么这些将播放。

  • 如果您想要交互式svg,请使用<iframe><object>

  • 如果您需要为旧浏览器提供使用svg插件的能力,请使用<embed>

  • 对于cssbackground-image中的svg和类似属性,现代主义是切换到回退图像的一种选择,另一种是取决于多个背景来自动执行:

    div {
    background-image: url(fallback.png);
    background-image: url(your.svg), none;
    }
    

    注释:多个背景策略在Android 2.3上不起作用,因为它支持多个背景,但不支持svg。

另一个很好的阅读是这篇博客 on svg回退。

从IE9及以上,您可以在普通IMG标签中使用SVG。

https://caniuse.com/svg-img

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

<object><embed>有一个有趣的属性:它们可以从外部文档(考虑主域同源策略)获取对SVG文档的引用。然后可以使用该引用来为SVG设置动画、更改其样式表等。

鉴于

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

然后你可以做这样的事情

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");
});

找到了一个纯CSS和没有双重图像下载的解决方案。它不像我想要的那样漂亮,但它有效。

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

这个想法是插入具有回退样式的特殊SVG。

您可以在我的博客中找到更多详细信息和测试过程。

如果使用标签,则基于webkit的浏览器不会显示嵌入位图图像

对于任何类型的高级SVG使用,包括SVG内联提供了迄今为止最大的灵活性。

Internet Explorer和Edge将正确调整SVG的大小,但必须同时指定高度和宽度。

您可以在svg中添加onClick、onmouseover等。到SVG中的任何形状:onmouseover="top.myfunction(evt);"

您还可以在SVG中使用web字体,方法是将它们包含在常规样式表中。

注意:如果您从Illustrator导出SVG,则Web字体名称将是错误的。您可以在CSS中更正此问题并避免在SVG中乱搞。例如,Illustrator给Arial起了错误的名字,您可以这样修复它:

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

所有这些都适用于自2013年以来发布的任何浏览器

有关示例,请参见ozake.com。整个网站由SVG组成,除了联系表格。

警告: Web字体在Safari中不精确地调整大小-如果您有很多从纯文本到粗体或斜体字的转换,则转换点可能会有少量额外或缺失的空间。有关更多信息,请参阅我在这个问题上的答案。

最好的选择是在不同的设备上使用SVG图像:)

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

使用srcset

大多数目前的浏览器支持srcset属性,它允许为不同的用户指定不同的图像。例如,您可以将其用于1x和2x像素密度,浏览器将选择正确的文件。

在这种情况下,如果您在srcset中指定了一个SVG,而浏览器不支持它,它将回退到src

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

这种方法与其他解决方案相比有几个好处:

  1. 它不依赖于任何奇怪的黑客或脚本
  2. 这很简单
  3. 您仍然可以包含alt文本
  4. 支持srcset的浏览器应该知道如何处理它,以便它只下载它需要的文件。

此jQuery函数捕获svg图像中的所有错误,并将文件扩展名替换为备用扩展名

请打开控制台查看错误加载图像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">

我个人会使用<svg>标签,因为如果你有完全控制它。如果你在<img>中使用它,你就不能用CSS等控制SVG的内部。

另一件事是浏览器支持

只需打开您的svg文件并将其直接粘贴到模板中。

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

然后在你的CSS中,你可以简单地例如:

svg {
fill: red;
}

一些资源:SVG提示

如果您需要您的SVG可以完全使用CSS样式化,它们必须内联在DOM中。这可以通过SVG注入来实现,它使用Javascript在页面加载后用SVG文件的内容替换超文本标记语言元素(通常是<img>元素)。

下面是一个使用SVGInject的最小示例:

<html>
<head>
<script src="svg-inject.min.js"></script>
</head>
<body>
<img src="image.svg" onload="SVGInject(this)" />
</body>
</html>

加载图像后,onload="SVGInject(this)将触发注入,<img>元素将被src属性中提供的文件内容替换。这适用于所有支持SVG的浏览器。

免责声明:我是SVGInject的共同作者

我的两分钱:截至2019年,93%的正在使用的浏览器(以及每一个浏览器的最后两个版本的100%)可以在<img>元素中处理SVG:

在此处输入图片描述

图片来源:我可以使用

所以我们可以说没有理由再使用<object>了。

然而它仍然有它的优点

  • 当检查时(例如使用Chrome开发工具),您会看到整个SVG标记,以防您想篡改它并看到实时更改。

  • 它提供了一个非常强大的后备实现,以防您的浏览器不支持SVG(等等,但它们中的每一个都支持!),如果找不到SVG,它也可以工作。这是XHTML2规范的一个关键特性,类似于betamax或HD-DVD

但是也有缺点

我建议使用的组合

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

您可以使用<img>超文本标记语言间接插入SVG,这在StackOverflow上是可能的,如下所述:

我的PC上有以下SVG文件

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

我已将此图像上传到https://svgur.com

上传终止后,我获得了以下URL:

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

然后我有手动(不使用IMAGE图标)添加以下html标签

<img src='https://svgshare.com/i/kyc.svg' title='Intersection of 3 Circles'/>

结果就在下面

使用data:image

对于有疑问的用户,可以看到我在编辑以下答案关于StackOverflow插入SVG图像时做了什么

备注-1:SVG文件必须包含<?xml?>元素。一开始,我只是创建了一个直接以<svg>标签开头的SVG文件,但没有任何效果!

备注-2:在开始时,我尝试使用Edit ToolbarIMAGE图标插入图像。我粘贴了我的SVG文件的URL,但StackOverflow不接受这种方法。<img>标签必须手动添加。

我希望这个答案可以帮助其他用户。

在大多数情况下,我建议使用<object>标签来显示SVG图像。感觉有点不自然,但如果你想提供动态效果,这是最可靠的方法。

对于没有交互的图像,可以使用<img>标签或CSS背景。

对于某些项目,内联SVG或iFrame是可能的选项,但最好避免<embed>

但是如果你想玩SVG之类的东西

  • 改变颜色
  • 调整路径大小
  • 旋转svg

用嵌入的那个

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

对我来说,一个简单的替代方案是将svg代码插入到div中。这个简单的示例使用javascript来操作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>

尽管w3School不推荐<embed>标签,但它是唯一让我的svg在Chrome中使用混合模式和掩码的东西:

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

而Firefox对

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

Chrome没有渲染渐变:

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

两种浏览器中的<object><img>也是如此。

根据个人经验,我建议在图像标签中通过src加载svg文件,如果您有许多svg图标或动态附加在一个页面上,它会变慢并且性能不好

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


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

但是如果你想在hover中分配css样式,你必须使用embed

只使用<svg>标签更容易,因为您的代码会运行得更快,并且您直接使用您的svg。要仅获取svg标签,请复制不带xml标签的svg文件。结果将是这样的:

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

这里总结了我能找到的将SVG插入超文本标记语言模板的所有方法,以及它们的区别和主要优缺点:

(((1))

/* in CSS */
background-image: url(happy.svg);

这种方式既不允许JS交互,也不允许CSS本身 可以对svg部分进行更细粒度的控制。

(((2))

<img src="happy.svg" />

就像(((1)))一样,既不允许JS交互,也不允许CSS本身对svg部分有更细粒度的控制。

方法(((1))和(((2))只有在需要静态svg时才可以。

注意:使用<img>标签时,如果您在srcset属性中指定了SVG,而浏览器不支持它,它将自动回退到src属性。

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

((3))

<div>
<!-- Paste the SVG code directly here. -->
<svg>...</svg>
<!-- AKA an inline svg -->
<!-- would be the same if is created and appended using JavaScript. -->
</div>

此方法没有(((1))和(((2)))中提到的任何警告,但是,此方法使模板代码混乱,并且SVG是复制粘贴的,因此它们不会在自己的单个文件中。

(((4))

<object data="happy.svg" width="300" height="300"></object>

或:

<object data="your.svg" type="image/svg+xml">
<img src="yourfallback.jpg" />
</object>

使用此方法,SVG将无法使用外部CSS访问,但可以使用JavaScript访问。

(((5))

使用ICONFU/SVG注入功能将svgs保存在单个文件中(并且还可以保持模板代码更干净),现在使用<img>标签注入svgs,但随后svg-注入将它们转换为内联svgs,因此CSS和JavaScript都可以访问它们。

注意1:如果动态添加#EYZ,此方法也有效(如果使用JavaScript添加img标签)。

注意2:使用此方法添加的SVG也会像图像一样被浏览器缓存。

(((6))

使用单个SVG精灵文件,然后使用<use>标签插入它们。这种方式也非常灵活,具有与(((5))相同的效果。这种方法(以及更多)在这个视频中展示了实际效果。

((7))

(React特定的方式)将它们转换为React组件(或编写一个加载它们的组件)。

(((8))

<embed src="happy.svg" />

根据MDN的说法,大多数现代浏览器已经弃用并删除了对浏览器插件的支持。这意味着如果您希望您的网站在普通用户的浏览器上可操作,依赖<embed>通常是不明智的。