用SVG 制做 Sprites的图标系统

https://css-tricks.com/svg-sp...javascript

我一直是图标字体的大力支持者。不少网站真的须要一个图标系统,图标字体提供了一个该死的精细系统。可是,我认为假设你对 IE 9+ 很好,使用内联 SVG 而且 <use> 引用图标的元素是一个优秀的系统。php

首先让咱们介绍它的工做原理。css

处理图标的一个好方法是让文件夹中包含大量.svg文件。html

folder-of-svgs.png

这是使用SVG的一个很酷的事情 - 它们是源文件。
它们能够是彩色的,而不是彩色的,多种形状,尺寸等等。java

svg-whatever.png

你可让 Illustrator(或其余任何软件)保存它,享受其带来的全部瑕疵:git

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<g>
    <path d="M50.049,0.3c14.18,0.332,25.969,5.307,35.366,14.923S99.675,36.9,100,51.409c-0.195,11.445-3.415,21.494-9.658,30.146 - yadda yadda yadda"/>
</g>
</svg>

合并.svg文件

若是须要,能够手动执行此操做。我作到了 您甚至没必要查看最终文件。只是称之为 svg-defs.svg或其余。github

它应该只是一个 <svg> 标签,带有<defs>标签(这意味着你要定义之后要使用的东西),而后是一堆<g>(组)标签。每一个<g>标记都有一个惟一的ID,包含每一个图标的全部路径和诸如此类的东西。web

<svg>
  <defs>

    <g id="shape-icon-1">
      <!-- all the paths and shapes and whatnot for this icon -->
    <g>

    <g id="shape-icon-2">
      <!-- all the paths and shapes and whatnot for this icon -->
    <g>

    <!-- etc -->

  </defs>
</svg>
事实证实 <symbol>多是一个更好的选择 <g>。参考 关于它的内容

能够手工完成,但固然这有点费力。Fabrice Weinberg建立了一个名为grunt-svgstore的Grunt插件,可自动执行此操做。shell

若是从未使用过Grunt,那么您能够这样作。这是一个能够帮助入门的截屏视频。npm

你能够安装它:

npm install grunt-svgstore --save-dev

确保该任务可用于:

grunt.loadNpmTasks('grunt-svgstore');

而后在配置中:

svgstore: {
  options: {
    prefix : 'shape-', // This will prefix each <g> ID
  },
  default : {
      files: {
        'dest/svg-defs.svg': ['svgs/*.svg'],
      }
    }
  }
},

在输出文件中svg-defs.svg,每一个图标(来自源.svg文件的任何路径和内容)将被包装在<g>带有惟一的前缀ID和文件名(减去.svg)的标记中。喜欢:

<g id="shape-codepen">

将SVG注入文档顶部
字面上包括它,如:

<!DOCTYPE html>
<html lang="en">

<head>
  ...
</head>

<body>
  <?php include_once("processed/svg-defs.svg"); ?>

或者你想要那样作。

遗憾的是,它必须位于顶部,由于有一个Chrome错误,若是稍后定义,这将没法正常工做。虽然......这个故事还有更多内容,由于当我输入这些单词时,这个网站使用的主题是在文档底部定义的图标,而且它有效。Ughkgh很困惑。

随时随地使用图标

如今你能够在任何地方使用它们!喜欢:

<svg viewBox="0 0 100 100" class="icon shape-codepen">
  <use xlink:href="#shape-codepen"></use>
</svg>
请注意, grunt-svgstore如今正在使用, <symbol>所以您甚至不须要使用viewBox!
确保在svg上使用这些类名来调整它的大小。
/* Do whatever makes sense here.
   Just know that the svg will be an 
   enormous 100% wide if you don't 
   reign in the width. */
.icon {
  display: inline-block;
  width: 25px;
  height: 25px;
}

Yay:你能够用CSS设置它们(和它们的部分)的样式

咱们喜欢图标字体的缘由之一是可以使用CSS设置样式。这项技术可让咱们尽咱们所能,并且更多,由于:

  1. 咱们能够设计全部单独的部分
  2. SVG有更多你能够控制的东西,好比特殊的过滤器和笔画

svg(有点像是)在DOM中,因此也能够用JavaScript。这里有一些造型可能性的各类演示:

codepen.io

<svg viewBox="0 0 100 100" class="icon shape-codepen">
  <use xlink:href="#shape-codepen"></use>
</svg>

<svg viewBox="0 0 100 100" class="icon shape-codepen-2">
  <use xlink:href="#shape-codepen"></use>
</svg>

<br>

<svg viewBox="0 0 100 100" class="icon shape-youtube">
  <linearGradient id="gradient"  gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="0%" y2="100%">
<stop stop-color="#FF0000" offset="0"/><stop stop-color="#571C1C" offset="1"/>
</linearGradient>
  <use xlink:href="#shape-youtube"></use>
</svg>

<br>

<svg viewBox="0 0 100 100" class="icon shape-twitter">
  <use xlink:href="#shape-twitter"></use>
</svg>

<svg viewBox="0 0 100 100" class="icon shape-twitter-2">
  <use xlink:href="#shape-twitter"></use>
</svg>

<svg viewBox="0 0 100 100" class="icon shape-twitter-3">
  <use xlink:href="#shape-twitter"></use>
</svg>
Result
EDIT ON
.hide {
  display: none;
}

.icon {
  width: 75px;
  height: 75px;
}

body {
  padding: 20px;
}

/* Targeting inside only */
.outer-ring {
  fill: #999;
}
.inner-logo {
  fill: #666;
}
.shape-codepen-2 {
  -webkit-filter: drop-shadow(5px 5px 2px #ccc); 
  filter: drop-shadow(5px 5px 2px black);
}

.shape-youtube {
  fill: url(#gradient);
}

.shape-twitter-2 {
  fill: #55ACEE
}
.shape-twitter-3 {
  fill: red;
}

请参阅CodeCen上的Chris Coyier(@chriscoyier)的Pen EBHlD。

另外一种方式:IcoMoon

IcoMoon以生成图标字体而闻名,实际上也能够很好地生成SVG精灵。选择所需的全部字体后,单击底部的SVG按钮,您将得到该输出,包括带有内联SVG方法的演示页面。

icomoon-out.jpg

浏览器支持

在浏览器支持方面,危险区域是IE 8和向下,Safari 5和向下,iOS 4.3和向下,以及Android 2.3和向下。但若是你的政策是“最后两个主要版本” - 你会看到几乎100%的支持。

请记住,图标只能用做支持角色,就像老是伴随着一个单词同样。若是是这样的话,那么支持并不算太大。若是它们是独立的,而且不显示会使网站没法使用,那么这是一个大问题。

我可能会选择图标字体,由于那里的支持更深。只要确保你作得对。

会变得更好的

理想状况下,咱们可以作到这一点:

<svg viewBox="0 0 100 100" class="icon shape-codepen">
  <use xlink:href="/images/svg-defs.svg#shape-codepen"></use>
</svg>

这确实在某些浏览器下是能够的,这意味着你能够不用将svg包括在文档的顶部。但意味着额外的 HTTP 请求,但这也意味着能够更有效地利用缓存(而不是膨胀文档缓存)。在测试中,Jonathan Neal 发现你须要拥有 xmlns 属性<svg>才能使它工做:

<svg xmlns="http://www.w3.org/2000/svg">

但即便这样,任何IE都没有支持。除非你想把整个换成<svg><use>一个<object>,这确实有效。乔纳森尼尔再次想到这一点:

/MSIE|Trident/.test(navigator.userAgent) && document.addEventListener('DOMContentLoaded', function () {
  [].forEach.call(document.querySelectorAll('svg'), function (svg) {
    var use = svg.querySelector('use'); 

    if (use) {
      var object = document.createElement('object');
      object.data = use.getAttribute('xlink:href');
      object.className = svg.getAttribute('class');
      svg.parentNode.replaceChild(object, svg);
    }
  });
});

他的演示如今还有一个方法,它对内容进行Ajax请求并注入,这容许填充在IE 9中工做。效率不高,但更像是polyfill。

我想有一天会直接<svg><use>.svg链接起来。甚至可能<img>在SVG上使用URL片断标识符。

浏览器<use>像阴影DOM同样对待:

如今,咱们能够针对<path>具备CSS 的我的进行定位,例如:

.targetting-a-path {
  fill: red;
}

但这会影响该路径的全部实例。你认为你能够这样作:

svg.shape-version-2 .targetting-a-path {
  fill: red;
}

但这不起做用。它穿过阴影DOM边界。理想状况下,您可使用“帽子”选择器来打破:

svg.shape-version-2 ^ .targetting-a-path {
  fill: red;
}

可是,这也没有获得支持,而且不彻底清楚这是否确实如何起做用。

与图标字体比对

基于矢量:领带

CSS风格: SVG精灵略有优点(定位部分,SVG特定造型,如笔画)

奇怪的失败: SVG彷佛正常工做(支持时)。图标字体彷佛以奇怪的方式失败。例如,您将字符映射到普通字母,而后字体加载失败,您会获得随机字符。或者你映射到“私人使用区”,一些浏览器决定将它们从新映射到真正奇怪的角色,如玫瑰,但它很难复制。或者你想在CDN上托管@font-face文件,但这是跨域的,Firefox讨厌这个,因此你须要你的服务器提供正确的跨源头文件,但你的Nginx设置不是正确的,唉。SVG赢得了这一局。

语义:并非什么大不了的事,但我以为<svg>对于一个图像来讲比<span>更有意义。

可访问性:也许有人能够告诉我?咱们应该/能够给出<svg>一个title属性吗?或者<text>咱们在视觉上隐藏的元素?
更新:该<title>元素能够有。或者也许是<desc>此SVG访问规范中使用的元素。

易用性:像 Fontello 和 IcoMoon 这样的工具很是适合图标字体工做流程,但我认为,与 Grunt 一块儿将它们拼凑在一块儿的文件夹 - 完整的SVG更加容易。

引用外部svg文件

svg 经过use能够在页面中引用屡次, 但前提是svg里内嵌的,若是是外部的, 能够借助下面的脚原本实现:

https://github.com/jonathantn...

相关文章
相关标签/搜索