iconfont渐变色实现方案总结

简介: iconfont渐变色实现方案总结

iconfont是前端技术中重要的一环——它能够方便地沉淀大量设计资产,并通过组件化的方式高效地在各种场景复用。而单纯应用iconfont,只能支持到纯色渲染图标,越来越难以满足高品质视觉效果的诉求。本文结合实际工作业务场景,调研了两种常见渐变iconfont实现方案,并提供icon组件封装demo,与各位读者分享。


背景


为在淘内打造家装本地化产品心智,设计同学近期对业务的主题样式做了升级,采用整体黑金色调替换了原有淘宝橙色设计。为了突出家装行业奢华质感,设计对背景、文字、图标等大量采用了白-金渐变色样式。



在众多页面、组件中,存在大量可复用的渐变色图标,本着DRY(Don't Repeat Yourself)的原则,我们当然不能每次都去切个图。于是封装了一套能够支持渐变色的iconfont组件,将调研过程以及实现思路在此分享一下。


实现效果


通过本文的方式,我们最终沉淀了业务的Icon组件,通过简单的调用方式即可快速实现渐变色图标。



<Icon   type="star"   color="#D5B198"/>
<Icon   type="star"   color="#D5B198"  // 设置渐变色,在支持的场景自动渲染,不支持的场景降级为color指定的纯色  gradientColor="linear-gradient(150deg, #FFFDFC 0%, #D5B198 100%)"/>


实际渲染效果如下:



渐变实现方案


业务内使用的iconfont均为font-class形式,以下实现方案也都基于该方式。iconfont的渐变色方案,也自然演变为寻找字体渐变色的方案。下面介绍在实现过程中了解到两种实现字体渐变色的方案,供大家参考。


 background-clip


background-clip用来设置元素背景(背景色或背景图)的延伸范围,通常有三个取值:content-boxpadding-boxborder-box ,即分别延伸到盒子模型的content区域、padding区域和border区域。


实现文字的渐变,我们用到了该属性的第四个取值:text 。即将元素背景的延伸范围限制在其内部文字的范围内。换句话说,只有文字的下方有背景。但单纯指定这个还不够,我们都知道元素的内容都是展示在背景之上,而且文字都是有颜色的,所以单独使用该css属性不会有任何实质的视觉效果——背景色展示在文字下方,又被文字盖住了。为了让背景色透出来,我们还需要将文字颜色去掉,最简单的方法就是将他们的颜色指定为透明色。


所以,一个简单的demo可以这么写:


<div class="gradient-test">  柴七TEST</div>




.gradient-test {  color: transparent;  background-image: linear-gradient(45deg, blue, red);  background-clip: text;  // 下面这两行不是必要的属性,单纯为了让文字大一点便于查看效果  font-size: 50px;  font-weight: 700;}


效果如下:



TIP:部分老版本浏览器对该属性的支持需要添加-webkit- 前缀。在生产应用中,为达到最大兼容性,最好同时声明-webkit-background-clip: textbackground-clip: text



 mix-blend-mode: darken


apple官网中,可以学习到另一种实现方案。使用css的属性mix-blend-mode


简单介绍下什么是“混合模式”:就是描述当前绘制的图像,如何与其下方的底色相作用的。在不设置的情况下,绘制的图像颜色会直接盖住底色。混合模式的可取值非常多,这里介绍的文字渐变色方案只用到了“变暗(darken)”这个混合模式,其他的不再一一介绍。


混合模式的“变暗”,就是对比当前要绘制的像素和其下方的像素,比较每个色彩通道(即R、G、B)的色值,取较小的作为最终结果。举个例子,我有一个红色(255,0,0)的像素,要绘制在蓝色(0,0,255)的背景上,当混合模式指定为变暗时,最终绘制结果为纯黑色(0,0,0),计算过程如下:


R = min(255, 0) = 0

G = min(0,0) = 0

B = min(0, 255) = 0


apple工程师巧妙利用了这一特性,其首选绘制了一个纯黑色背景+白色文字的元素作为整体的背景。白色的三个色彩通道均为最大值255,而黑色均为最小值0,那么当任何图像与这样的背景色做变暗混合时,白色部分的混合结果一定是该图像的原始像素,黑色部分一定是黑色。通过这样的方式,我们可以将文字下方的图案以文字的轮廓展示出来,也就可以支持到渐变iconfont。


假定像素(r, g, b)

对黑色部分R = min(r, 0) = 0;G = min(g,0) = 0;B = min(b, 0) = 0,最终展示(0,0,0),即黑色

对白色部分R = min(r, 255) = 0;G = min(g,255) = 0;B = min(b, 255) = (r,g,b),最终展示(r,g,b),即该像素本身


纯黑色背景+白色文字

上面铺一个iphone 14 pro的小黑紫渐变图

设置小黑紫图片mix-blend-mode: darken


这个方法充满了艺术感,但是也有局限性——最终混合得到的结果的容器区域一定是有纯黑背景色的,在一些活动页可能有较好的应用场景,但却不能用于iconfont——因为iconfont的要求一定是字体部分有颜色,其他部分为透明色。所以最终并没有采取该方案。


react组件设计


前面提到,我们业务中使用的iconfont方案是font-class,即类似这样的使用方式:



<span class="ahome-icon-notice"></span>


其css实现简单可描述为如下代码:



.ahome-icon-notice::before {  content: "notice对应的iconfont字符"}


这其实天然是一个容器包含了文字的形式,使用background-clip方案,我们只需要对文字的容器进行样式定义即可。


 简单demo



const Icon: FC<IIconProps> = props => {  const {    type,    gradientColor,    ...restProps  } = props;
  return (    <span      className={cs(        className,        'ahome-iconfont',        `ahome-icon-${type}`,        {          'gradient-icon': !!gradientColor,        }      )}      style={{        backgroundImage: gradientColor      }}      {...restProps}    />  );};


对应的css样式(省略掉了部分不重要的样式)



.ahome-iconfont.gradient-icon {    -webkit-background-clip: text;    background-clip: text;    color: transparent;}


 使用媒体查询优雅降级


单纯知道上面的实现方法还不够,要投入生产应用,还有一个事情要考虑:当运行环境不支持background-clip时,如何优雅降级?这里可以使用媒体查询。思路可以简单一句话概括:只有在支持background-clip的环境里,才设置文字颜色为透明;且在不支持该属性的环境里,将容器的background-image设为none。


@supports (background-clip: text) {  .ahome-iconfont.gradient-icon {    -webkit-background-clip: text;    background-clip: text;    color: transparent !important;  }}
@supports not (background-clip: text) {  .ahome-iconfont.gradient-icon {    background-image: none !important;  }}


image.png总结

iconfont本质是字符,所以寻找iconfont渐变色渲染的方案可以转化为寻找字符渐变色渲染的方案。通过css的backgroud-clip: text或者mix-blend-mode:darken属性都可以实现字符渐变色渲染,但是后者会导致容器区域存在黑色背景,不适合图标场景。最终在实际生产应用时,还需要根据自己的业务受众,考虑在较老环境中的优雅降级。

团队介绍

我们是大淘宝技术-品牌行业前端团队,目前负责消费电子、家装家居、汽车、运动户外、快消的线上线下零售新模式的探索,面向淘内淘外,提供商家、门店、消费者最佳用户体验。团队在XR、3D、2D渲染引擎这些创新体验上有不错的沉淀,同时面向全栈领域团队探索了 Serverless 云端研发模式,在消费者前台,通过端智能等手段提升消费者效率,同样面向工程领域,在跨端、前端工程化、中后台微前端都有一些沉淀,如果你是一位充满想象的终端极客,欢迎你的加入,通过自己的技术想法去改变淘系品牌行业业务的终端表达。

相关文章
|
2月前
|
前端开发 UED
如何使用css给一个盒子加上好看的hover阴影效果
如何使用css给一个盒子加上好看的hover阴影效果
92 1
|
4月前
|
前端开发
CSS 遮罩层,背景渐变
CSS 遮罩层,背景渐变
43 4
|
7月前
|
前端开发
CSS圆角大杀器,使用滤镜构建圆角及波浪效果
CSS圆角大杀器,使用滤镜构建圆角及波浪效果
78 0
|
7月前
css3边框与圆角
css3边框与圆角
61 0
|
前端开发
【前端切图】CSS文字渐变和背景渐变
【前端切图】CSS文字渐变和背景渐变
79 0
9、CSS3新增样式(边框圆角、阴影、形变)
9、CSS3新增样式(边框圆角、阴影、形变)
126 0
9、CSS3新增样式(边框圆角、阴影、形变)
|
前端开发
CSS学习笔记 05、边框、圆角与盒子阴影(一)
CSS学习笔记 05、边框、圆角与盒子阴影(一)
CSS学习笔记 05、边框、圆角与盒子阴影(一)
|
前端开发
CSS学习笔记 05、边框、圆角与盒子阴影(二)
CSS学习笔记 05、边框、圆角与盒子阴影(二)
CSS学习笔记 05、边框、圆角与盒子阴影(二)
|
移动开发 前端开发
CSS - H5 Swiper 快速滑动白色闪屏解决方案
CSS - H5 Swiper 快速滑动白色闪屏解决方案
627 0
CSS - H5 Swiper 快速滑动白色闪屏解决方案
|
前端开发
CSS - 移动端 1px 像素边框问题的解决方案(Border.css)
CSS - 移动端 1px 像素边框问题的解决方案(Border.css)
279 0
CSS - 移动端 1px 像素边框问题的解决方案(Border.css)