CSS 图标换色指南:用 brightness / invert / mask 把任意图片改成想要的颜色

用 CSS 让图片(图标)变成任意颜色:brightness / invert / mask 全讲清

起因:一个蓝底按钮上的蓝色图标"看不见",用一行 CSS 把它刷白。顺手把这类"给图片变色"的技巧整理成篇。

0. 先记住一条底层规则

filter 里这些函数只改颜色通道(RGB),不改 alpha 通道

也就是说:图标的形状、透明背景都不会变,只会变颜色。这是所有"用 CSS 给图标换色"技巧成立的前提(前提是图片得是「形状 + 透明底」的 PNG/SVG,不能是一整张不透明的 JPG)。

另一个特性:filter 可以串联,从左到右依次生效。


1. 变白:brightness(0) invert(1)

最常用的一招。深色底 / 彩色底上想让图标变白:

css 复制代码
.icon {
  width: 16px;
  height: 16px;
  filter: brightness(0) invert(1);
}

原理是两步:

步骤 蓝色像素 #2583FF 透明像素
原图 #2583FF alpha = 0
brightness(0) #000000(亮度 ×0 → 任何颜色都压成纯黑 仍透明
invert(1) #FFFFFF(100% 反相 → 黑变白 仍透明

为什么不能只写 invert(1) 因为直接反相蓝色得到的是橙黄,不是白:

复制代码
#2583FF  ──invert(1)──▶  #DA7C00   橙黄,不是我们要的

#2583FF  ──brightness(0)──▶  #000000  ──invert(1)──▶  #FFFFFF   正确

brightness(0) 的作用是"归一":不管原图是蓝、绿还是花的,先统一压成黑,再翻白就没有意外。


2. 变黑 / 变深灰:brightness(0)

浅色底上,彩色图标往往显得"太跳",压成深色更协调:

css 复制代码
/* 纯黑 */
.icon { filter: brightness(0); }

/* 深灰(更柔和,常用在浅灰底上) */
.icon { filter: brightness(0); opacity: 0.72; }

这是最省事的一招------不用抠图、不用换资源,一个 filter 就得到一个"单色深版"图标。


3. 变灰 / 禁用态:grayscale(1)

按钮 disabled、图标"不可用"的常见视觉:

css 复制代码
.icon-disabled {
  filter: grayscale(1);
  opacity: 0.4;
}

配合 hover 可以做成"变亮"的交互:

css 复制代码
.icon { filter: grayscale(1) opacity(.4); transition: filter .2s, opacity .2s; }
.icon:hover { filter: none; opacity: 1; }

4. 变任意精确色 :推荐 mask(而不是继续加 filter)

如果只想要白色/黑色,第 1、2 节够了。但要"精确 指定一个品牌色"(比如 #FF6B00),靠 filter 串联是很痛苦的:

css 复制代码
/* 不推荐:参数靠试,还不精确 */
filter: brightness(0) invert(1) sepia(1) saturate(5) hue-rotate(350deg);

更优雅的做法是不用图片的颜色,只用它的形状 ------ mask

css 复制代码
.icon-recolor {
  width: 16px;
  height: 16px;
  background-color: #ff6b00;                                  /* 想要什么颜色就写什么 */
  -webkit-mask: url("./icon.png") no-repeat center / contain;  /* 用图片的 alpha 做遮罩 */
  mask: url("./icon.png") no-repeat center / contain;
}

原理:mask 用图片的 alpha 通道 当"镂空模板",不透明的地方透出 background-color,透明的地方保持透明。

mask 方案的好处:

  • 颜色精确可控 ,写什么色就是什么色(还能用 linear-gradient 做渐变图标);
  • 可以配合 transition: background-color平滑换色动画
  • 想换色只改 background-color 一行,不用再碰 filter 参数。

注意事项:

  • 必须加 -webkit-mask 前缀(移动端 WebView 尤其);
  • 原图必须是带透明背景的 PNG/SVG(用 alpha 当模板)。整张不透明的图会变成一整块色块;
  • 如果图片边缘有抗锯齿的半透明像素,接缝处仍能平滑过渡(这正是用 alpha 而不是简单阈值的好处)。

5. 顺手的两个"图片效果"技巧

贴合形状的投影:drop-shadow(不是 box-shadow

css 复制代码
.icon {
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
}

区别很关键:

阴影范围
box-shadow 元素的矩形盒子(透明区域也会投影,方方正正一格)
drop-shadow 图片实际图形轮廓(只沿着图形边缘投,自然得多)

处理透明 PNG 图标、不规则图形时,drop-shadow 明显更对。

提亮 / 压暗 / 模糊

css 复制代码
filter: brightness(1.2);   /* 提亮 20% */
filter: brightness(0.8);   /* 压暗 20% */
filter: blur(2px);          /* 模糊(做占位图/毛玻璃氛围) */
filter: contrast(1.2);      /* 加对比 */

6. 速查表

需求 写法 备注
彩色 → 纯白 brightness(0) invert(1) 深底/彩底最常用
彩色 → 纯黑 brightness(0) 浅底
彩色 → 深灰 brightness(0) opacity(.72) 更柔和
彩色 → 任意精确色 background-color + mask 推荐,可做渐变/动画
禁用态 / 变灰 grayscale(1) opacity(.4) 配合 hover 恢复
贴形状投影 drop-shadow(...) 优于 box-shadow
模糊 blur(2px) 占位、氛围

7. 几个容易踩的坑

  1. 图片必须"形状 + 透明底"brightness(0) invert(1) 把整张 JPG 变成一片白,mask 也会得到一整块色块。
  2. 半透明边缘 :PNG 的抗锯齿像素是"半透明色",被 filter 着色后会变成"半透明白",在深底上可能看到一圈淡淡的光晕。追求极致清晰的话,改用 SVG 图标 (+ fill: currentColor),或直接用字体图标(van-icon / iconfont)------它们本来就是"随字号/颜色变化"的矢量。
  3. 性能filter / mask 会触发图层合成。长列表里不要给每个 item 都挂带 transition 的 filter ,容易掉帧;必要时给容器加 will-change 或只在 hover 时加。
  4. 兼容性filter → Android WebView 4.4+ / iOS 9+;mask → 需带 -webkit- 前缀。移动端项目可放心用,但要写全前缀
  5. 留一行注释 :如果图标以后换成了白色资源,那行 filter: brightness(0) invert(1) 就该删掉。写下"为什么",避免后人误删或对着它发愣。

8. 选型建议:什么时候用什么

复制代码
只要白 / 黑 / 灰        →  filter(一行搞定)
要精确品牌色、要渐变/动画 →  mask + background-color
要"随文字颜色变化"       →  SVG + fill: currentColor(最优雅)
要是空心/实心多套图标     →  直接找设计出图,别硬用 CSS 拼

一句话:CSS 能解决的问题就别加图片资源;但需要多色或复杂图形时,也不要为了省资源把 CSS 写成一串魔法参数。

相关推荐
我命由我123451 小时前
CSS - CSS 媒体查询 orientation
前端·javascript·css·html·css3·html5·js
zhanghaha13147 小时前
HTML系列教程:18_HTML / CSS 颜色零基础详解
css·html·tensorflow
Aaswk7 小时前
从 HTML/CSS/JS 到 Vue + Axios 的一篇实战笔记
前端·css·vue.js·html
xieliyu.1 天前
前端基础:常见CSS选择器用法
前端·css·笔记·vscode
cll_8692418913 天前
WordPress Single Post 文章页美化:响应式表格、图片优化与自动悬浮 Table of Contents(CSS + JS)
前端·css
愛芳芳3 天前
基于 Electron + Vue3 的仿 PC 微信客户端项目实战
前端·javascript·css·elementui·typescript·electron·vue
feixing_fx3 天前
伪类与伪元素的魔法:纯 CSS 打造炫酷的按钮悬停特效
前端·css·css3
Peter-Code4 天前
微前端避坑指南:主应用与子应用的高度及滚动条协调
css·前端框架·微前端
梦帮科技5 天前
Next.js 16 模块化单体实战:App Router、领域模块与 Route Handler 分层
css·数据结构·链表·正则表达式·node.js·json·html5