还有一篇关于此主题的 较新的文章,涵盖了一些较新的信息。
内联 SVG 是一种使用 SVG 的绝佳方式,因为除了其他原因之外,构成图形的各个形状都可以被脚本化和设置样式。 这些形状就在 DOM 中。 但这是否意味着我们必须在每个页面上的 HTML 中定义这些形状? 不,我们可以使用 <use>
从其他地方引用它们。 理想情况下,这个“其他地方”应该是一个外部文件,**因为这意味着该文件可以被浏览器缓存**,效率!
这就是我的意思
<!-- `<use>` shape defined ON THIS PAGE somewhere else -->
<svg viewBox="0 0 100 100">
<use xlink:href="#icon-1"></use>
</svg>
<!-- `<use>` shape defined in an EXTERNAL RESOURCE -->
<svg viewBox="0 0 100 100">
<use xlink:href="defs.svg#icon-1"></use>
</svg>
所以,是的:外部资源 = 最佳选择。
但是,外部资源的方式在任何版本的 Internet Explorer(测试过 11 个版本)中都不起作用。 即使是那些支持内联 SVG 的版本:9、10、11。
幸运的是,Jon Neal 有一个巧妙的解决方案。 它是一个名为 SVG for Everybody 的小脚本。 想法是:就像它起作用一样使用 <use>
,该脚本将在 IE 9、10、11 中处理它。 一个 polyfill,只是针对这种情况(它不会在任何不支持内联 SVG 使用的地方起作用)。
它的工作原理是这样的
- 如果浏览器是 IE 9、10 或 11(用户代理嗅探,但这是这里的主要目的)。
- 针对引用的 SVG 文件执行 Ajax 操作
- 根据引用的 ID(例如 #icon-1)查找所需的位
- 将该内容注入到页面上的
<svg>
中

我认为内联 SVG 非常有用,而这个(微型)脚本意味着你可以以更负责任(可缓存)的方式使用它。
IE 的限制因素到底是什么? 使用
<use>
本身还是使用带有外部资源的<use>
?如果我没弄错的话,IE10 及以下版本不会渲染使用 DEFS 定义并使用 USE 调用的 SVG。
例如:http://www.dblok.net/svgtest.html
使用 http://netrenderer.com/ 我看到只有 IE11 渲染了 SVG。
我认为 IE11 渲染了 SVG,但是只有当源 SVG 不是外部的时候(但我让 Chris 确认一下)。
带有外部源的
<use>
在 IE 9、10、11 中不起作用。 这就是这篇文章的重点 =)很棒的文章,感谢分享这个 polyfill…
我尝试过在其他情况下让它工作,但没有成功…有人知道网上有没有这个的已知正常工作演示,可以下载和玩玩…
我通过逆向工程已知正常工作文件来学习得最好…
我让它工作了…接下来将尝试 polyfill….再次感谢你提供所有关于 SVG 的信息…
Michael!
我在文章中链接了一个工作演示:https://css-tricks.cn/examples/svg-for-everybody/
嘿 Chris,我是 Gilles,我们在 BTConf 见过面(那个高个子的法国人)。 我有没有告诉你你在那里很棒?:)
这就是我星期一的想法。 这就是我想要告诉你的。
我的想法是将你的 SVG 代码放在一个 JS 文件中,它是一个带有 document.write 的 JavaScript 字符串。
这是一个这样的文件,其中包含两个 svg:http://www.dblok.net/svgtest.svg.js)
这里有一个 pen,它在 js 中整合了这个文件,然后通过 USE 标签调用了两个独立的 SVG:http://codepen.io/gfra/pen/xzGIo
没有 JS ajax 调用,没有多个 http 请求,而且 js 文件在第一次访问后就被缓存了!
我的 SVG/JS 文件有点糟糕,我在星期一的酒店里快速完成了它,我没有互联网帮助我以良好的格式语法来完成它。
非常聪明!
你只需要使用一个构建工具来为你创建这个 JS 文件,就像你创建 defs.svg 文件一样。
我唯一担心的是
document.write
。 我认为这通常被认为是不好的(通常被称为“邪恶”),虽然我不记得确切的原因。 我认为它与性能有关,因为它会停止解析和执行内容。是的,在性能方面它非常糟糕(我认为它会像撒旦本人一样重建 DOM,甚至更糟),但这个想法值得尝试!
FYI 我也尝试过这种技术
它也很糟糕,但…它也可以工作!
哦,我认为我的技巧在 IE 中仍然不起作用….polyfill 会获取对应 ID 的实际 SVG 代码…
我的错!
Opera 浏览器是否允许标签?
好的 polyfill! 我创建了一个小的 gulp 插件 gulp-svgstore,它将 svg 合并成一个,可能值得在这里提到。 我一直将其与 gulp-inject 一起使用到 body 标签中,但现在切换到外部源了。
我刚刚尝试了这种技术,我发现我完全正确地使用了所有东西。 但是,它在 Chrome 中没有显示任何内容。 我检查了控制台,发现我收到一个“不安全的尝试加载 URL”错误。 我快速将其放入 CodeKit 中,它完美地工作了。 可能每个人都知道这一点,但是当你以本地方式开发时,使用这种技术可能会遇到一些跨域问题,如果你没有使用服务器进行开发。 希望这能帮到某人。 再次感谢你发布这篇文章 Chris,它恰好对我很及时。
为什么在 Firefox 29 中使用 svg 或 Icon 字体有时页面会完全变成黑色? 滚动鼠标它将部分显示出来。 这是 Firefox 的一个 bug 吗?
为什么是“甚至”?
嘿 Chris,
首先,感谢你的文章。 我有一个关于使用 标签的问题。 是否仍然可以访问 SVG 的路径? 比如说,我在一个锚标签之间通过
<use>
标签调用了一个 SVG。 是否可以这样说:a:hover svg { fill: purple; }
?感谢你出色的工作!
但仍然没有 HTML Iinncludes…
我在 IE9 中发现了一个问题。 控制台写道:“完成此操作所需的数据尚不可用。 文件:svg4everybody.js,行:37,列:4”。 有任何想法吗?
不知道是否有人发布了这个。 但它就在这里,在 Grunt 中删除手动部分。
https://npmjs.net.cn/package/grunt-svg-combine
我不明白 Chris 的优势所在。 为什么从外部文件提供 SVG 形状比在每个页面的顶部包含形状(例如通过 php include,如你在之前的文章中所建议的那样)更好?
毕竟,svg 形状通常由非常小的文本文件描述,通过在页面的顶部包含这些形状,你将节省 2 次服务器请求(一次用于 svg 文件,一次用于 js pollyfill)。
缓存真的会在这里产生很大的影响吗?
假设每个文档的顶部都有 15k 的图标。
等等。
如果它们在外部资源中并被缓存
等等。
你期望人们访问的页面越多,以及你拥有的图标大小越大,影响就越大。
是的。缓存总是会产生影响,即使在某些情况下你无法注意到它。
但是,因为它在你的页面第一次调用时添加了一个 http 请求,所以它可能是一个很好的问题。页面的第一次调用速度不会很快,如果它必须调用你的 CSS、JS 和 JS 库(并不总是托管在 CDN 上)以及另一个用于你的 SVGS 的文件,并且等待所有这些文件下载才能开始渲染页面。
我最近读到,为了提高加载速度,谷歌建议 Web 开发人员直接在 HTML 代码中定义页面的前半部分的样式,以便在整个 CSS 文件加载之前页面就可以开始渲染。这是一个非常奇怪的建议,但是,嘿,这是谷歌,你想对他们做什么。
我仍然对这个建议感到困惑。无论如何,考虑到这个想法,也许你想要在你的页面中包含你的 SVGs,但我认为这不是一个好主意。
谢谢 Chris,这是一个有用的解释。
关于最上面的 "为什么",它是否实际上是由于它是被替换的元素 - 来自操作系统级别?它是一个自闭合标签的事实不应该影响它太多,对吧?
闭合标签是否是由于它需要包含内容而产生的?也许应该提到这一点,以避免对这种非标准标记造成混淆。
否则,看起来很棒,期待将来有更多对 shadowDOM 的支持。
当我尝试这个方法时,我非常喜欢它,并且已经认为这是 SVG 图标的未来 - 但后来我发现它在 Android 上不起作用,即使是 4.2 版本,所以它完全没有用。 :(
在 Android 上不起作用确实很可惜。我不关心 IE8,但 Android 却很重要 :P
出于另一个原因,我尝试使用一个真正的外部路径来引用 SVG 文件。
有点奇怪...
似乎这个有效(127.0.0.1 同样有效)
而这个失败了(内部网络 IP)
来自真实外部资源的文件也失败了。像
还是我漏了什么?
p.s.
代码块功能没有显示我的代码,这就是为什么我省略了 '>' '<'
请看这里
我认为这是浏览器的限制,跨域文件无法加载,只能在同一域中加载。我也尝试过(我的 Chrome 浏览器)。
是的,你说得对。我不知道它是这样处理的。
应该从模式中看出这一点...
谢谢!
我有点迟到了,但在尝试 svg4everybody(很棒)和 IE8 回退时,我注意到它没有将你
element 的任何类转移到
。这意味着如果你已经对 svg 进行了样式设置(例如浮动),它将不会应用于 IE8 回退。如果你使用的是 Selectivizr,一个快速修复方法是使用
.my-svg-icon ~ img
- 似乎 IE8 默认情况下将开闭 " 标签视为它不理解的独立元素,这意味着它们、use
标签和img
都是兄弟元素。啊,打字错误 - 它没有将你 svg 元素中的任何类转移到生成的 img 标签。
并且 IE8 默认情况下将开闭 svg 标签视为独立元素。
预览帖子选项发生了什么!
我似乎完全无法让它工作。
使用最新的 Chrome 浏览器,当 SVG 文件包含在页面中时,我可以 "使用" SVG,但是当我应用这种方法时,一切都崩溃了。在 SVG 应该出现的地方,什么都没有显示。
我已经检查了代码很多次了。我不知道该怎么办。
任何调试技巧都将不胜感激。
所以,事实证明,来自 Iconmoon 的一个全新的 SVG 可以正常工作,但是,用 SVGO 运行它就会失败。
在 cordova 应用程序中似乎不起作用,我不得不将 svg 与 defs 内联到 body 中。我猜这是因为 file:// 协议。
这似乎只有在我指定了
因此,在使用 grunt-svgstore 生成我的 sprite 时,我不得不添加
我不确定这是否被认为是正确的做法?
另外,
viewBox
大小似乎在放置到外部 SVG 文件时有效,所以如果它在 gruntfile 中(如上所示),那么我们可以稍微缩短 HTML