正在寻找更好的 SVG 图标方法?内联 SVG 可能是您的最佳选择,您可以在 这篇较新的文章 中了解相关信息。
您可以设计一个图标集,其中所有图标都具有完全相同的纵横比。但这通常不会发生。一个小烧杯图标周围的容器可能是又高又窄。小鱼周围的容器可能是又短又长。您可能不必过多考虑这一点,但不幸的是,当您使用 我之前描述过的 SVG 图标系统 时,您确实需要考虑这一点,因为您需要使用 viewBox
属性来描述该容器/纵横比。
一种改进方法是在 SVG 中使用 元素,而不是直接引用形状(或
),因为您可以直接在
上定义
viewBox
,然后在稍后在 中
它时就不需要使用它了。
需要举个例子。
以下是两个纵横比截然不同的图标,从 Illustrator 中的画板可以看出。

我们可以调整它们,使它们都放置在一个一致的纵横比内,但我发现,知道图标的边缘正好是形状停止的地方,而不是在其周围有任意数量的空白区域,这样更灵活、更易于操作。
“旧”方法
如果我们采用 块路线,我们可以将它们组合成
然后像这样使用它们
这使得实现者需要承担相当大的责任,以确保标记中 viewBox
属性的正确性。这就是为什么您可能希望尝试使所有这些图标都具有一个一致的 viewBox="0 0 100 100"
(或类似内容),但这会导致出现某种任意空白区域问题的原因之一。
“新”方法
让我们来了解一下 Fabrice Weinberg 和 TxHawks。Fabrice 从事 grunt-svgstore 的开发工作,这是一个用于从 SVG 文件文件夹创建 SVG 精灵的 Grunt 插件。这种方法使 SVG 图标工作流程变得快速而轻松。也就是说,除了您需要在使用每个图标之前知道该死的 viewBox
之外。
TxHawks 建议 grunt-svgstore 至少在包装每个图标的 元素上放置
data-*
属性,以便可以以编程方式访问它应该是什么。但不幸的是,SVG 不允许这样做(它可能已经可以工作了,但不妨使构建工具符合规范)。但这没关系,因为很快,他们建议 使用 ,结果证明这是一个非常好的主意。
不要使用 来包装所有图标形状,而是使用
,如下所示
请注意,每个图标的 viewBox 都已定义,并且您是在定义它而不是在使用它时定义它。这意味着使用它变得更容易
更轻松,更不容易出错。
而且它变得更好:您可以添加
原始文件的描述
感谢 TxHawks 和 Fabrice,grunt-svgstore 现在可以做到这一点!
为什么 <symbol> 更适合图标
总结一下
- 可以在 symbol 上定义
viewBox
,因此您无需在标记中使用它(更轻松且更不容易出错)。 - 可以在
内添加
title
和desc
标记,并且当使用该 symbol 时,它们会“顺带一起”,从而更容易实现可访问性。 - symbol 在定义时不会显示,因此不需要
块。
- 这可能就是
的发明初衷。
演示
它有效
查看 Chris Coyier 在 CodePen 上撰写的笔 Hwcxp(@chriscoyier)。
漂亮。我一定会在我当前的项目之一中尝试一下。谢谢 Chris!
这是一个很棒的想法!
symbol 是否在内联 SVG 支持的任何地方都受支持?
哇。这项技术正是我在另一篇关于 SVG 文章 的文章之后一直在寻找的。
我有一组都是 SVG 但视口不同的图像,动态包含,并且可以通过 CSS 进行样式设置,而不是我以前必须使用的方式(糟糕的图像切换)。我认为我将非常频繁地使用这种技术。感谢 Chris 和同事们!
不是要破坏一场精彩的游行……但在我的系统上……运行 Chrome 35 的 Windows 8 pro……Codepen 中的鲨鱼符号被截断了……
在我的同一系统(Windows 8 pro)上,但使用 Firefox 29,鲨鱼看起来不错……
IE 11 也看起来不错……
即便如此……伟大的帖子……
Michael Whyte
如果这能让你放心,在我的 Windows 7 上的 Chrome 37 上看起来非常好。
它有可能是一个临时错误,修复程序很快就会发布。
在我看来,Chrome 35 上的鲨鱼看起来不错,但是一旦我放大,它就开始被截断。缩小也会出现类似情况,它只是缩小。我知道在更改缩放级别时,某些东西容易出错,但我以前从未见过如此剧烈的变化。
糟糕。另一个 SVG 实现错误。
“好”消息是它与 <symbol> 或 <use> 元素无关(存在大量 <use> 元素错误)。
坏消息是它适用于任何图形内容
a. 使用百分比度量进行大小调整,或者具有基于百分比的默认大小调整(例如引用 <symbol> 元素的 <use> 元素——默认大小为高度和宽度的 100%)。
b. 位于使用默认坐标系的 SVG 内部(即,它没有自己的 viewBox 属性)。
正如 @Charles 指出的那样,在默认浏览器设置下该问题不可见,但如果放大或缩小浏览器窗口,它就会显示出来。我没有较新 Chrome 的测试版,但我确实在 Opera 上对其进行了测试,并且遇到了相同的问题,因此这看起来像是 webkit 源代码中的深层问题。
Chromium 问题 334526 看起来相关,没有提到即将发布的修复程序。
http://codepen.io/AmeliaBR/pen/stAki?editors=110
最近在一个项目中使用这种技术时,我也遇到了同样的问题,解决方法是在 :( 上添加 viewBox。
如果有人找到其他解决方案,请分享!
这是我使用 svg 图标精灵时遇到的唯一一个问题(我仍然使用它们并且喜欢它们),现在它已解决!感谢您的精彩表现,我迫不及待地想在下一个项目中使用它,并且不必再担心那些令人讨厌的 viewBoxes 了。
太棒了!我希望有人能解决 view box 问题。我一定会优先使用它而不是字体图标。
万岁!感谢您辛勤的探索,Chris。
这终于是我一直在等待的将 http://stackicons.com 从基于字体图标转换为基于 SVG 的缺失部分!
Gulp 插件:https://npmjs.net.cn/package/gulp-svg-icons/
你是否已经找到一个使用gulp进行png回退的简洁解决方案?
一个重要的提示。它确实简化了标记。
关于title和desc元素的说明:并非所有浏览器/屏幕阅读器组合都能从使用<use>元素复制的元素中获取描述性文本。因此,在符号内部定义标题在使用符号时可能实际上不会产生任何影响。
这些元素的屏幕阅读器支持总体上目前不如预期的那样好,但我记得我见过其他测试指出了<use>的具体问题(抱歉,找不到链接)。
希望对内置辅助功能的支持很快就会得到改善,但在此期间,如果文本描述对于图标的含义至关重要,Web开发人员可能需要考虑其他插入文本描述的方法(请参阅链接的文章以了解示例)。
我刚刚尝试了这种方法,发现如果我放大页面,符号在其viewBox中无法正确显示,因为viewBox是在defs中定义的。但是,如果我使用.,则不会发生这种情况。
我刚刚也发现了这一点。有什么解决方案吗?
这在我的运行IE6的新Windows XP机器上不起作用。
这真是太棒了。但是,为了使此方法有效,这些图标仍然需要设置宽度和高度,并具有相同的纵横比,对吧?现在,为了实现流畅性,您仍然需要使用该填充底部技巧!
无法使包装器SVG缩小以适合其内容,就像包含比例宽度图标字体的span可以做的那样。符号会缩小或扩展以适应SVG,并根据preserveAspectRatio属性进行调整,但如果您想更改实际的SVG尺寸以匹配比例,则需要为每个纵横比添加额外的CSS规则。
“填充底部技巧”在符号本身上的“切片”preserveAspectRatio属性下可以正常工作,尽管仅当您对
overflow:visible
CSS规则很宽容时才有效。您必须在Chrome和IE的符号上以及Firefox的嵌套<svg>上允许它(因为它们实现<use>元素的方式)。但是,仅使用底部填充,您最终会在图标正方形内获得一个顶部对齐的图像。如果您尝试对preserveAspectRatio使用居中值,它会在SVG的“官方”高度内居中,不包括填充,因此您需要在顶部和底部填充内居中SVG才能使事情正常工作。如果您缩小比例以使官方SVG尺寸导致符号在水平方向上溢出SVG,则情况也会变得奇怪。
另一种方法是在SVG本身应用viewBox和preserveAspectRatio属性,但这会抵消使用具有自身viewBox属性的符号获得简洁标记的好处!
http://codepen.io/AmeliaBR/pen/lykCm/?editors=110
我真的希望SVG2最终能采用更好的内联SVG自动缩放规则,这样我们就不必再像这样进行hack了……
很棒的教程先生……#未来派
切换到
symbol
的另一个好处是它允许合并来自原始SVG的defs
块到生成的SVG中,从而使我们能够在图标中使用渐变、剪切路径等。这意味着
将变成
因此允许我们一致地在所有
symbol
中use
在原始SVG内部定义的渐变。但是,这意味着为了渲染渐变,我们需要使用
visibility:hidden;
而不是display:none;
隐藏svg。我想我会高兴得哭出来。上周我还在处理viewBox参数,并且不太明白为什么它给我带来了这么大的麻烦。
还有其他人发现这种技术在IE中使用标签包含外部SVG精灵时不起作用吗?我知道IE不允许使用外部svg文件OOB(尽管Microsoft表示目前正在考虑)。
我正在使用svg4everybody,它以前可以工作,但现在切换到符号后,它拒绝工作。有什么想法吗?
抱歉,打错了。意思是“使用‘use’标签包含外部SVG精灵”。
此技术在任何浏览器中都无法按预期方式与外部SVG一起使用。viewBox属性将被忽略,无论它是在外部<symbol>还是<svg>元素上。与<use>技术一样,IE将完全忽略外部SVG。
您使用<symbol>的无JavaScript选项是
1. 仅使用内部SVG。
2. 始终将viewBox属性添加到每个SVG。
您的JavaScript选项是
1. 猜测并遵循您希望成为本机的语法。
2. 使用完全唯一的语法。
恕我直言,所有这些选项都是有效的。要求一个永远不会出错的JavaScript是永远不必为每个页面上的每个SVG编写viewBox属性的值得的缺点。
同时,我将追求选项1:http://discourse.specifiction.org/t/simple-svg-markup/92
感谢你的回复Johathan,只有一两件事。
我认为这不是真的。我已经成功地使用了外部符号SVG。它在除IE之外的所有浏览器上都能正常工作。
我认为无JavaScript选项不适用于大型项目,因此只剩下JS选项。
我仍在考虑这里最好的方法是什么,但如果我找到令人满意的解决方案,我会更新此线程。
我刚才说的那个SVG的事情。完全错了。不是100%错。但大部分错了。我仍在针对<g>进行测试。IE仍然不支持外部SVG。我已经更新了https://github.com/jonathantneal/svg4everybody以与<symbols>一起使用。
不错,以后得试一试。这种方法如何与其他元素垂直对齐?
目前使用display table & table cell。
我们提供的这些新方法令人兴奋,虽然一切都很紧张,但它们确实提供了新的机会。
此致。
你能详细说明使用
symbol
而不是(嵌套)svg
的好处吗?有吗?示例
大家好
是否可以使用css3关键帧动画在symbol标签中动画化路径?在我的情况下不起作用。
示例:http://codepen.io/anon/pen/Hfbmr
此致 Philip
顺便说一句,这不是强制性的,但SVG 1.1规范建议将
symbol
元素放在defs
中以提高清晰度和可访问性。不过,这可能更多的是理论上的,而不是对可访问性产生真正影响。这太棒了
矢量(已选中)
多色(已选中)
所有矢量资源只需一次服务器访问(已选中)
这是圣杯
嘿,这似乎真的很酷!我认为使用此技术与grunt-svgstore一起在项目中使用足够酷。但我注意到一个很大的警告,我希望你能帮我解决。你是如何处理悬停状态的?当您选择要赋予悬停状态的svg时,它将不起作用,因为当您仅使用“.”时,您无法选择实际的svg形状。另一方面,如果您直接选择形状,例如
#icon-arrow
,它将不起作用,因为您实际上从未悬停过此形状,因为您看到的形状只是对它的引用……还是?您能分享任何想法/经验吗?非常感谢!
我对此的解决方案:http://codepen.io/jjenzz/pen/AxLKz
所以,看起来是在头部声明的符号路径中使用`fill=”currentColor”`使得这成为可能?
您可以添加原始SVG中未使用的规则,例如`stroke`或`stroke-width`。
其他规则,例如默认的`fill`,可以使用花哨的值来编写,因此无法应用并稍后修复。演示
这实际上是对↑Flavio Gortana的回复 https://css-tricks.cn/svg-symbol-good-choice-icons/#comment-1583277
你好,
好消息。Chrome Canary v.38已解决所有缩放问题。
事实证明,
必须位于文档中的上方,否则此技术将无法正常工作。因此,您不能将所有图标都放在文档的底部。
在Webkit缩放页面时发现了符号问题。
http://monosnap.com/image/SRqgBNCb6qSjT12yAYPtxb5poXgdMI
代码在此 – http://codepen.io/vikmind/full/sAmjK/