初来时发现团队内项目对图标的使用上,已经形成了围绕 svg 的一套 设计 & code 规范:
- 图标基本是 svg 作为组件引入项目中
- 设计师使用 svg 的 fill 属性来控制图标颜色,方便开发使用 css 直接变换颜色
优势就是一些 hover 之类的复杂交互状态下,需要图标变色时,可以直接通过 css 控制颜色,而不是引入多张像素图,确实比较方便。 但是这种方式依然存在一些问题
- css 中每次需要变色时在单独处理 css fill 等属性,效率低下
- 一些色彩丰富的图是没有设计变色状态的,不应该被复用的交互变色 css 覆盖样式
- 一些颜色是通过 stroke 而不是 fill 实现,fill 反而被用作透明 filter 掉底色
- 复杂的非规则图形,使用 path 实现,大小上相较于 png 反而没有容量优势
基于遇到的问题,逐步探索出了一些经验以及方法
scss mixin
首先使用 scss mixin 构建了一个 快捷方法
scss
/** 可以保持 文本颜色与 svg 颜色一致 */
@mixin colorWithSvg($color: #ffffff) {
& {
fill: $color;
path {
fill: $color;
}
ellipse {
stroke: $color;
fill: $color;
}
}
}
进一步解决 不需要变色的 svg 的问题 以及 只想要影响 svg 不影响文本色
问题 3 中只能规范设计,而 filter 底色的问题 css 不会覆盖 path 上的 fill-opacity ,实际使用时注意实际效果即可
因为多色图标属于少数,所以在项目中引入 svg 时手动添加一个 owner-color 属性来标记不需要被变色的 svg
html
<svg owner-color="true" ...></svg>
scss
/** svg 填充色 */
@mixin colorFillSvg($color: #ffffff, $svgCheckOwner: false) {
@if $svgCheckOwner {
&:not([owner-color]) {
// ...
}
} @else {
& {
// ...
}
}
}
/** font color 与下级 svg 填充色一致 */
@mixin colorWithSvg($color: #ffffff, $svgCheckOwner: false) {
color: $color;
svg {
@include colorFillSvg(currentColor, $svgCheckOwner);
}
}
svg 压缩
svg 如果绘制了一个非常复杂的图形,那么将会失去他的体积优势,这时候就需要对 svg 进行压缩,可以参考张鑫旭 - SVG 在线压缩合并工具
当前 svg 使用时需要注意的是能使用的 安全压缩选项 是有限的,压缩后仍需要注意检查,路径精度压缩 即可压缩大部分体积
有选择地使用 svg
在实际使用中可以总结出 svg 的优点:
- 变色方便(需要检查实际效果)
- 无损放大
- 体积小(简单图形,需要注意压缩路径精度)
但仍有一些缺点:
- 复杂图形体积大,2x.png 小得多
- 相同 svg 在一个上下文中,def 会因为当前生效 css 互相影响
- 变色仍有一定的限制
- document reflow/repaint 影响性能
所以 svg 图标还是一个需要花费精力处理的资源类型,不能盲目追求 svg 化