https://css-tricks.com/svg-sp...
我一直是图标字体的大力支持者。很多网站真的需要一个图标系统,图标字体提供了一个该死的精细系统。但是,我认为假设你对 IE 9+ 很好,使用内联 SVG 并且 <use>
引用图标的元素是一个优秀的系统。
首先让我们介绍它的工作原理。
处理图标的一个好方法是让文件夹中包含大量.svg
文件。
这是使用SVG
的一个很酷的事情 - 它们是源文件。
它们可以是彩色的,而不是彩色的,多种形状,尺寸等等。
你可以让 Illustrator(或其他任何软件)保存它,享受其带来的所有瑕疵:
<?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
或其他。
它应该只是一个 <svg>
标签,带有<defs>
标签(这意味着你要定义以后要使用的东西),然后是一堆<g>
(组)标签。每个<g>
标记都有一个唯一的ID,包含每个图标的所有路径和诸如此类的东西。
<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插件,可自动执行此操作。
如果从未使用过Grunt,那么您可以这样做。这是一个可以帮助入门的截屏视频。
你可以安装它:
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设置样式。这项技术可以让我们尽我们所能,而且更多,因为:
- 我们可以设计所有单独的部分
- SVG有更多你可以控制的东西,比如特殊的过滤器和笔画
svg(有点像是)在DOM中,所以也可以用JavaScript。这里有一些造型可能性的各种演示:
<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方法的演示页面。
浏览器支持
在浏览器支持方面,危险区域是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里内嵌的,如果是外部的, 可以借助下面的脚本来实现:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。