我是否将<img>,<object>或<embed>用于SVG文件?

art*_*ung 565 html svg vector-graphics

我应该使用<img>,<object><embed>加载SVG文件到一个页面类似于加载的方式jpg,gif还是png

每个代码的代码是什么,以确保它尽可能地工作?(我在我的研究中看到了包括mimetype或指向后备SVG渲染器的参考,并没有看到一个很好的最新参考).

假设我正在检查与Modernizr的 SVG支持,并<img>为不支持SVG的浏览器退回(可能用普通标签替换).

Eri*_*röm 600

我可以推荐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>
Run Code Online (Sandbox Code Playgroud)

*)嗯,不完全是免费的,因为有些浏览器下载了这两种资源,请参阅Larry关于如何解决这个问题的建议.

2014年更新:

  • 如果你想要一个非交互式的svg,请使用<img>脚本回退到png版本(对于较旧的IE和android <3).一个干净简单的方法:

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

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

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

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

  • 对于css background-image和类似属性中的svg ,modernizr是切换到后备图像的一种选择,另一种是依赖于多个背景来自动执行:

    div {
        background-image: url(fallback.png);
        background-image: url(your.svg), none;
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

这篇关于svg后备的博客文章还有一个很好的解读.

  • 此方法将始终下载光栅文件.[这个答案](http://stackoverflow.com/questions/8946134/conditional-code-for-displaying-png-in-place-of-svg-for-older-browsers#answer-8946347)确保后备是仅在旧版IE浏览器上请求. (8认同)
  • 设置尺寸的正确方法是什么?我是否包含高度和宽度属性,还是使用CSS? (7认同)
  • 使用css很好,或者在嵌入元素上设置大小(即:iframe,embed,object,img) - 后者的作用是它可以避免在定义大小的样式表之前的flash-of -sty -led-content已加载.还要确保svg具有viewBox属性,并从svg根元素中删除width/height属性.根据我的经验,这将给你最好的crossbrowser行为. (5认同)
  • 我认为更快的人们停止支持古代浏览器的速度越快,我们就会越快建立一个让他们的浏览器保持最新状态的社会,甚至从2012年开始自动使用浏览器.唯一的借口是没有免费访问现代浏览器,但Firefox例如,仍然支持Windows XP(可能是52版).总有一个现代和免费的替代品. (4认同)
  • 请注意,上述内容不适用于Adobe SVG插件.但是,如果在`<object>`标记内添加`<param name ="src"value ="your.svg"/>`,你可以全部工作(现代浏览器+ ASV + MSIE).我花了很长时间试图弄清楚如何做到这一切,我想我终于明白了. (3认同)
  • 需要注意的是(至少在 Chrome 上)使用 `&lt;object&gt;` 标签不会缓存 SVG 文件,而使用 `&lt;img&gt;` 标签会缓存文件。 (2认同)

Chr*_*ren 107

从IE9及以上版本,您可以在普通的IMG标签中使用SVG ..

https://caniuse.com/svg-img

<img src="/static/image.svg">
Run Code Online (Sandbox Code Playgroud)

  • 如果SVG需要加载其他资源,则此方法无效.(字体,图像......) (31认同)
  • 使用`<img rel="nofollow noreferrer" />`标签的任何人可能想知道附加[SVG Fragement标识符](https://www.w3.org/TR/SVG/linking.html#SVGFragmentIdentifiers),例如"`<img rel="nofollow noreferrer" src = "myimage.svg #svgView(preserveAspectRatio(none))"/>`",它允许您控制宽高比,`viewBox`等与内联SVG定义相同.进一步阅读扩展 - https://css-tricks.com/scale-svg/ (12认同)
  • 对于徽标或图标,我仍然建议出于语义原因使用IMG标记,并确保SVG只是一个矢量图. (8认同)
  • 现在到处接受.@artlung,你可能想改变你的答案. (4认同)

WGH*_*WGH 94

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

特定

<object id="svg1" data="/static/image.svg" type="image/svg+xml"></object>
Run Code Online (Sandbox Code Playgroud)

然后你可以做一些事情

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");
});
Run Code Online (Sandbox Code Playgroud)

  • @ SteveO'Connor我不知道,也许它没有很好的文档记录,但它肯定适用于Firefox,IE11和Chrome.至少对于外部SVG文件:我无法使用数据URI. (5认同)
  • 我认为这是最好的答案 (2认同)

Rob*_*lís 26

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

<img src="your-svg-image.svg" alt="Your Logo Alt" onerror="this.src='your-alternative-image.png'">
Run Code Online (Sandbox Code Playgroud)

  • @artlung他的观点是正确的.请参考,https://css-tricks.com/using-svg/ (4认同)
  • 有趣.但如果svg没有呈现,你能确定`onerror`会发生火灾吗?你测试过哪些浏览器? (3认同)

Scr*_*her 22

使用 srcset

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

在这种情况下,如果你指定了一个SVG srcset并且浏览器不支持它,那么它将回退到src.

<img src="logo.png" srcset="logo.svg" alt="My logo">
Run Code Online (Sandbox Code Playgroud)

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

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

  • 确保每个人都能准确看到网页的一部分,谷歌会更爱你! (5认同)
  • 为什么这些天有任何浏览器支持SVG的可能性超过99%? (3认同)
  • 看起来比现在更好,因为在当前时间点,您将后备图像推向约10%的用户. (2认同)
  • @沃尔克。10%?caniuse 显示缺乏 SVG 支持 [大约 2%](https://caniuse.com/#search=svg)。我仍然像在答案中一样使用 srcset 来支持 2%。未来,我希望浏览器能够获取诸如 srcset 之类的信息,并根据性能和大小等因素选择合适的图像,而不仅仅是设备大小或文件格式支持。 (2认同)
  • 此解决方案的唯一问题是浏览器仅支持SVG,而不支持srcset。例如IE11,即使它支持SVG也默认返回PNG (2认同)

ade*_*hox 17

以下是我能找到的将 SVG 插入 HTML 模板的所有方法及其差异及其主要优缺点的总结:

(((1)))

/* in CSS */
background-image: url(happy.svg);
Run Code Online (Sandbox Code Playgroud)

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

(((2)))

<img src="happy.svg" />
Run Code Online (Sandbox Code Playgroud)

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

仅当您想要静态 svg 时,方法 ((( 1 ))) 和 ((( 2 ))) 才适用。

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

<img src="logo.png" srcset="logo.svg" alt="my logo">
Run Code Online (Sandbox Code Playgroud)

(((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>
Run Code Online (Sandbox Code Playgroud)

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

(((4)))

<object data="happy.svg" width="300" height="300"></object>
Run Code Online (Sandbox Code Playgroud)

或者:

<object data="your.svg" type="image/svg+xml">
  <img src="yourfallback.jpg" />
</object>
Run Code Online (Sandbox Code Playgroud)

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

(((5)))

使用iconfu/svg-inject将 SVG 保留在自己的单独文件中(以使模板代码更加清晰),现在使用<img>标签添加 SVG,并且 svg-inject 会自动将它们转换为内联 SVG,因此可以访问它们CSS 和 JavaScript。

注1:如果imgs 是动态添加的(使用 javascript),则此方法也适用。

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

(((6)))

使用单个 SVG 精灵文件,然后使用<use>标签插入它们。这种方式也很灵活,和(((5)))效果一样。视频中展示了此方法(以及其他一些方法)的实际操作。

(((7)))

(React 特定的方式)将它们变成 React 组件(或者编写一个加载它们的组件)。

(((8)))

<embed src="happy.svg" />
Run Code Online (Sandbox Code Playgroud)

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


And*_*ift 15

如果您使用<img>标签,那么基于webkit的浏览器将不会显示嵌入的位图图像.

如果您使用内联SVG,则Explorer将不会根据您的CSS 调整SVG的大小.
Explorer将正确调整SVG的大小,但您必须同时指定高度和宽度.

我发现<object>标签是唯一适用于所有浏览器的标签.我必须将宽度和高度(在SVG内)更改为100%才能使其正确调整大小.

你可以在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;    
}
Run Code Online (Sandbox Code Playgroud)

所有这些都适用于过去两年发布的任何浏览器.

结果在ozake.com(法语).整个网站由SVG组成,联系表格除外.

警告: Web字体未精确调整大小,如果您有大量从纯文本到粗体或斜体的过渡,则转换点可能会有少量额外或缺少的空间.有关详细信息,请参阅此问题的答案.


War*_*ama 14

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

这是使用SVGInject的最小示例:

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

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

免责声明:我是SVGInject的合着者

  • 您可以将 SVG 放在单独的文件中,但仍然可以使用 CSS 和/或 Javascript 访问它们。在某些情况下,您可以使用 webpack,这样您的 SVG 将内联在您的文件中,但如果您动态访问 SVG,SVG 注入基本上是实现此目的的唯一方法。 (2认同)

Laz*_*ana 11

我个人会使用<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>
Run Code Online (Sandbox Code Playgroud)

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

svg {
  fill: red;
}
Run Code Online (Sandbox Code Playgroud)

一些资源:SVG提示


ame*_*iel 9

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

在此处输入图片说明

资料来源:我可以使用

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

但是它仍然有其优点

  • 在检查时(例如,使用Chrome Dev Tools),您会看到整个SVG标记,以防您想稍作改动并查看实时更改。

  • 如果您的浏览器不支持SVG(等待,但每个浏览器都支持!),它提供了一种非常强大的后备实现。如果未找到SVG,它也可以使用。这是XHTML2规范的关键功能,例如betamax或HD-DVD

但是也有缺点


snt*_*ode 6

尽管 w3schools 不推荐该<embed>标签,但它是使我的具有混合图案和蒙版的 svg 在 Chrome 中工作的唯一因素:

<embed src="logo.svg" style="width:100%; height:180px" type="image/svg+xml" />
Run Code Online (Sandbox Code Playgroud)

而 Firefox 则没问题

<svg style="width:100%">
    <use xlink:href="logo.svg#logo"></use>
</svg>
Run Code Online (Sandbox Code Playgroud)

Chrome 没有渲染渐变:

<embed src="logo.svg" style="width:100%; height:180px" type="image/svg+xml" />
Run Code Online (Sandbox Code Playgroud)

两个浏览器中的<object>和都是一样的。<img>


Art*_*tru 5

找到了一种纯 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>
Run Code Online (Sandbox Code Playgroud)

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

更多细节和测试过程你可以在我的博客中找到。