使用 Grunticon 实现内联 SVG 以及回退

Avatar of Chris Coyier
Chris Coyier 发表

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费额度!

Grunticon 2 发布了!它有一个 很棒的新网站。Grunticon 是一个构建 SVG 图标系统的绝佳工具。其工作流程类似于:

  1. 准备一个包含 SVG 图标的文件夹
  2. 运行 Grunticon 处理该文件夹,它会生成你需要的一切
  3. 将 JavaScript 代码放在 <head>
  4. 在需要使用图标的地方,使用 HTML 代码 <div class="icon-image"></div>
  5. 图标无处不在!

Grunticon 2 甚至提供了一种注入内联 <svg> 的方法,这样你就可以获得所有优势,例如脚本、动画、CSS 控制等。你只需要添加一个属性

<div class="icon-burger alt" data-grunticon-embed></div>

使用 Grunticon 本身已经很棒了。只是它与我一直 讨论的另一种方法 有点不同,后者使用 SVG 雪碧图以及内联 <svg><use></use></svg>

我展示的方法是,你从在文档中需要图标的地方使用内联 <svg> 开始,然后处理回退。这种方法可能具有一些优势,例如:

  • 如果支持内联 SVG,则不会进行任何 DOM 操作,所有内容都会保留并正常工作。
  • 如果你决定不再需要回退,则可以很容易地将其删除。
  • (感谢 Scott 在下方指出的内容):如果**你不选择通过 AJAX 获取雪碧图,而是将其直接嵌入文档中**,则非 JS 用户将会获得 SVG 图标而不是回退 PNG。

内联 <svg> 优先的优点是,我们仍然可以使用 Grunticon 来帮助我们处理回退!

1. 获取包含 SVG 的文件夹 + 创建 SVG 雪碧图

你可以通过任何可能的方式获取/创建 SVG。这里我们将使用 IcoMoon,因为它简单易用并且可以立即提供 SVG 雪碧图。如果你想将雪碧图创建作为构建过程的一部分,请 阅读相关内容

2. 在文档中正常使用图标

简单示例

<button>
  <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-home">
    <use xlink:href="#icon-home"></use>
  </svg>
  Go Home
</button>

务必使用 xmlns="http://www.w3.org/2000/svg",这是在 IE 8 中为其提供布局所必需的。

3. 使用常规的 Grunticon 构建

在 Gruntfile.js 中

grunticon: {
  icons: {
    files: [{
      expand: true,
      cwd: "svg/",
      src: ["*.svg"],
      dest: "fallbacks/"
    }]
    // We don't need the enhanceSVG option here
  }
}

这会为你生成所有 PNG 回退内容。

4. 在文档的头部,执行内联 SVG 测试

Modernizr 有一个 很棒的内联 SVG 测试,我们将借用它。

var supportsSvg = function() {
  var div = document.createElement('div');
  div.innerHTML = '<svg/>';
  return (div.firstChild && div.firstChild.namespaceURI) == 'http://www.w3.org/2000/svg';
};

if (!supportsSvg()) {

  // Do Grunticon stuff

} else {

  // Ajax for SVG sprite

}

5. 如果测试表明支持内联 SVG,则使用 AJAX 获取雪碧图

我们之前 介绍过

var ajax = new XMLHttpRequest();
ajax.open("GET", "svgdefs.svg", true);
ajax.responseType = "document";
ajax.onload = function(e) {
  document.body.insertBefore(ajax.responseXML.documentElement,
                             document.body.childNodes[0]);
}
ajax.send();

这与回退无关,只是在支持的浏览器中获取图标的常规流程。我们这样做是为了使其在 IE 9/10/11 中正常工作,并且可以对雪碧图进行浏览器缓存。

6. 如果测试表明不支持内联 SVG,则使用 Grunticon

只是做了一些细微的修改,你需要删除 grunticon() 调用中的第一个 CSS 文件。那是支持 SVG 的文件,而我们已经涵盖了这种情况。

// Inline script of grunticon.load.js here
grunticon(["", "/fallbacks/icons.data.png.css", "/fallbacks/icons.fallback.css"]);

效果还不错

现代浏览器
在 IE 9 中仍然运行良好,在 IE 8 和 Android 上也很好地回退。

如果你还需要支持 IE 6 和 7...

目前,我们使用 <svg> 元素本身,并根据需要设置背景以实现回退。IE 8 可以做到这一点,但 IE 6 和 7 不行。SVG 元素会直接消失(即使你使用 HTML5Shiv,奇怪的是)。

如果你需要支持这些古老的浏览器,则将类名向上移动到一个包装 div 中

<div class="icon icon-credit">
  <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-arrow-right"><use xlink:href="#icon-arrow-right"></use></svg>
</div>

另一个值得注意的 IE 6-7-8 问题:你不支持 background-size,因此,请根据你要使用的确切大小生成 PNG。

代码库

为了防止我搞砸了东西,以及你们想修复它,我把这个概念放到了 一个代码库 中。