我一直是图标字体的拥护者。 许多站点确实需要图标系统,而图标字体则提供了一个很好的系统。 但是,我认为假设您对IE 9+很好 ,使用内联SVG和<use>
元素引用图标是一个很好的系统。
首先让我们介绍一下它是如何工作的。
处理图标的一种不错的方法是将一个文件夹包含.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>
同样,您可以手动执行此操作,但是这当然有点费力。 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错误 ,如果稍后定义,它将无法正常工作。 尽管...这个故事还有更多内容,因为在我键入这些单词时,该站点正在使用的主题在文档底部定义了图标,并且可以正常工作。 令人困惑。
随处使用图标
现在您可以在任何地方使用它们了! 喜欢:
<svg viewBox="0 0 100 100" class="icon shape-codepen">
<use xlink:href="#shape-codepen"></use>
</svg>
<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;
}
是的:您可以使用CSS为它们(及其零件)设置样式
我们喜欢图标字体的原因之一是能够使用CSS设置样式。 这种技术的优势在于,我们尽一切所能,甚至更多,因为:
- 我们可以为所有单独的部分设置样式
- SVG有更多可以控制的功能,例如特殊的滤镜和笔触
svg在DOM中是(kinda),所以JavaScript也是如此。 以下是一些样式化的可能性以及所有这些演示的示例:
请参阅CodePen上的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>
这在某些浏览器中确实有效,这意味着您可以跳过文档顶部的包含。 这种方式意味着一个额外的HTTP请求,但这意味着您可以更有效地利用缓存(而不是膨胀的文档缓存)。 在测试中,Jonathan Neal发现您需要在<svg>
上具有xmlns属性才能使其工作:
<svg xmlns="http://www.w3.org/2000/svg">
但是即使如此,任何IE都没有支持。 除非您想用<object>
交换整个<svg><use>
, 否则它将起作用。 乔纳森·尼尔(Jonathan Neal)再次指出 :
/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:
现在,我们可以使用CSS定位单个<path>
,例如:
.targetting-a-path {
fill: red;
}
但这将影响该路径的所有实例。 您认为可以做到:
svg.shape-version-2 .targetting-a-path {
fill: red;
}
但这是行不通的。 它越过了阴影DOM边界。 理想情况下,您将使用“帽子”选择器来打破这一点:
svg.shape-version-2 ^ .targetting-a-path {
fill: red;
}
但这还不被支持,而且还不清楚它到底是如何工作的。
“ Versus”图标字体
基于向量:领带
CSS样式: SVG精灵略有边缘(目标零件,SVG特定的样式,例如笔触)
奇怪的失败: SVG似乎可以正常工作(受支持时)。 图标字体似乎以奇怪的方式失败。 例如,将字符映射到普通字母,然后字体加载失败,并且随机字符很多。 或者,您映射到“私人使用区”,一些浏览器决定将它们重新映射到像玫瑰一样的真正奇怪的字符 ,但是很难复制。 或者您想将@ font-face文件托管在CDN上,但这是跨域的,Firefox对此很讨厌,因此您需要服务器提供正确的跨域标头,但是Nginx设置却没有正确的选择,SIGH。 SVG赢得了这一大奖。
语义:没什么大不了的,但是我认为<svg>
对于图像比<span>
更有意义。
辅助功能:也许有人可以告诉我? 我们可以/应该给<svg>
一个title属性或其他东西吗? 还是我们在视觉上隐藏的<text>
元素? 更新: <title>
元素可能起作用 。 或者,可能是此SVG访问规范中使用的<desc>
元素。
易于使用: Fontello和IcoMoon之类的工具对于图标字体工作流程而言相当不错,但是我认为,带有Grunt的满文件夹的SVG可以更轻松地将 它们 压缩在一起。
伊恩·费瑟(Ian Feather) 发表了一篇文章,介绍了为什么它们也不再使用图标字体,我同意每一点。
翻译自: https://css-tricks.com/svg-sprites-use-better-icon-fonts/