scss mixin svg 颜色控制 以及与 png 方案对比讨论

初来时发现团队内项目对图标的使用上,已经形成了围绕 svg 的一套 设计 & code 规范:

  • 图标基本是 svg 作为组件引入项目中
  • 设计师使用 svg 的 fill 属性来控制图标颜色,方便开发使用 css 直接变换颜色

优势就是一些 hover 之类的复杂交互状态下,需要图标变色时,可以直接通过 css 控制颜色,而不是引入多张像素图,确实比较方便。 但是这种方式依然存在一些问题

  1. css 中每次需要变色时在单独处理 css fill 等属性,效率低下
  2. 一些色彩丰富的图是没有设计变色状态的,不应该被复用的交互变色 css 覆盖样式
  3. 一些颜色是通过 stroke 而不是 fill 实现,fill 反而被用作透明 filter 掉底色
  4. 复杂的非规则图形,使用 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 化

相关推荐
里欧跑得慢1 天前
17. Flutter Hero动画实现:让界面过渡更加优雅
前端·css·flutter·web
IT_陈寒1 天前
Vue的这个响应式陷阱,我debug了一整天才爬出来
前端·人工智能·后端
kyriewen1 天前
前端测试:别为了100%覆盖率而写测试,那是自欺欺人
前端·javascript·单元测试
去伪存真1 天前
我自己写的第一个skills--project-core-standards
前端·agent
Data_Journal1 天前
如何使用cURL更改User Agent
大数据·服务器·前端·javascript·数据库
竹林8181 天前
wagmi v2 多链钱包切换:一个 Uniswap 仿盘项目让我踩了三天坑
前端·javascript
donecoding1 天前
Playwright MCP 页面捕获:Snapshot、截图、HTML 到底选哪个?
前端·ai编程·前端工程化
滕青山1 天前
在线PDF拆分工具核心JS实现
前端·javascript·vue.js
Smilezyl1 天前
一个独立开发者,靠一份 markdown 驱动 Claude Code, 用 20 天跑通 9 个包的 monorepo 工程
前端·人工智能·github
技术崽崽1 天前
不止有 Agent:Cursor 进阶使用技巧全解析
前端