评论

用纯 CSS 方式实现动态切换主题风格

动态主题风格切换是一个非常重要的功能,它可以允许应用程序用户在不同的场景下选择自己喜欢的主题。

一、前言

UI 组件库是现代 Web 应用程序开发中不可或缺的一部分。动态主题风格切换是一个非常重要的功能,它可以允许应用程序用户在不同的场景下选择自己喜欢的主题。这样的一个特性可以增加用户体验的个性化,并提高应用程序的可用性和易用性。

微盟移动端组件库 Titian 提供了动态主题切换的能力,并且延展了主题范围。


二、背景

在以前商户店铺的品牌视觉风格往往千篇一律,同时还因为需要逐个繁琐地配置界面中元素,导致的风格错乱等问题。针对上述的痛点,本次升级在确保商户品牌风格统一的前提下,基于品牌调性提炼了具有共性的视觉特征,分别为颜色、图标、圆角。并用这些特征组合为“通用”、“潮流”、“可爱”三套风格,能够让商家随心选择,让线上店铺更贴合自身的品牌调性,提高品牌识别度,维持 C 端用户的品牌心智。

微盟移动端组件库 Titian 的主题风格包括三个维度的风格变化:

1、主题颜色的风格切换,这里主题色可以设置任意一种色值。

2、字体图标风格的切换,组件库中的所有图标包含三种风格,具体分为通用型,超流型和可爱型。

3、所有组件的圆角的切换,组件库中所有圆角也分为三种风格,风格的分类和字体图标分类一致,通用型的圆角即为设计稿上的圆角,超流型的圆角则是所有的组件圆角都变成直角,可爱型的圆角则为在设计稿上的圆角的基础上加上8个像素。

我们要实现三种风格的切换是互相独立的,可以互相组合搭配。另外,图标风格的切换可以是全量一起切换,也可以是部分单独切换,而且需要运行时可以动态切换。

这些风格的切换都需要内置到组件库中,只需要给业务方提供一个变量来改变整体风格。


三、需求分析

对于主题色的风格配置,由于有些组件使用的的具有百分比透明度的主题色,所以采用 RGBA 色值更加方便。对于图标风格切换,从一种风格增加到三种风格,能不能尽量的不要增加代码体积,毕竟小程序对包体积有严格的要求。 对于圆角风格,有些需要将设计稿的圆角加8像素,有些需要变成直角,而有些又需要单独处理成大圆角。

这都该如何设计呢?这么多的风格切换,如何能尽量设计少的接口来让业务方写最少的代码,不去增加业务方的记忆负担呢?另外需要在运行时进行风格的切换,我决定使用 CSS 原生变量的方式。

CSS变量的好处包括:

代码重用:可以在多个元素中使用同一个变量,避免了重复编写样式代码的问题。

简化维护:当需要修改样式时,只需要修改变量的值,而不是每个元素的样式。

动态更新:CSS 变量可以通过 JavaScript 动态修改,使得样式在运行时可以动态变化。

提高可读性:通过使用有意义的变量名,可以使样式表更易于理解和维护。

CSS 变量可以提高代码的可维护性、可读性和灵活性。


四、技术方案和实施

4.1  主题颜色切换方案

组件库内部定义三个 CSS 变量:--theme-r、--theme-g、--theme-b,这三个 CSS 变量也是对外暴露出去修改主题颜色的关键。组件内部的全局 less 文件使用这三个变量定义主题色,所有组件使用到主题色的地方都统一使用下面的 less 变量。


@theme-r: var(--theme-r, 250);
@theme-g: var(--theme-g, 44);
@theme-b: var(--theme-b, 25);
@brand-color: rgb(@theme-r, @theme-g, @theme-b);
@brand-color-fade-10: rgba(@theme-r, @theme-g, @theme-b, 0.1);
@brand-color-fade-20: rgba(@theme-r, @theme-g, @theme-b, 0.2);
@brand-color-fade-30: rgba(@theme-r, @theme-g, @theme-b, 0.3);
@brand-color-fade-40: rgba(@theme-r, @theme-g, @theme-b, 0.4);
@brand-color-fade-50: rgba(@theme-r, @theme-g, @theme-b, 0.5);
@brand-color-fade-60: rgba(@theme-r, @theme-g, @theme-b, 0.6);
@brand-color-fade-70: rgba(@theme-r, @theme-g, @theme-b, 0.7);
@brand-color-fade-80: rgba(@theme-r, @theme-g, @theme-b, 0.8);
@brand-color-fade-90: rgba(@theme-r, @theme-g, @theme-b, 0.9);
@brand-color-fade-100: rgba(@theme-r@theme-g@theme-b1);



4.2  圆角风格切换方案

三种圆角是对应三种圆角数值,默认的圆角是设计稿的圆角,怎样变成直角和大8像素的圆角呢?我采用设计圆角加上增量圆角来达到最终圆角的目的。

针对于所有增量圆角,我们定义一个css变量:--base-radius-size,另外在全局less变量中定义圆角变量,我们所有使用到圆角的地方都使用less变量;默认的增量为0。

潮流型风格需要将圆角变成直角,那么只需将增量圆角设置为一个较大负值比如-999px,那么最终也会得到一个负数圆角,因为圆角不存在负值,所以负值圆角表现就是圆角为0的直角效果。

可爱型风格需要将设计稿圆角增加8像素。那么这个增量圆角就设置为8px;而对于那些特殊需求,要单独设置成大圆角即半圆形的圆角,那么只需给一个较大的圆角即可。但是为了做区分,所以这里新增了一个css变量:--capsule-radius-size,这个是专供特殊需求圆角使用,比如button和search的圆角,他们在可爱风格下会直接变成胶囊型圆角。那么这里就把--capsule-radius-size设置为999px即可。

下图就是全局 less 变量中定义的圆角,在组件中统一使用如下圆角。目前只罗列了4px、8px、12px、16px和大圆角。如果有更多圆角,可以新增多个圆角数值。业务方在使用时,设置通用风格,只需设置--base-radius-size:0px;--capsule-radius-size:0px;这也是默认风格。设置成潮流型,只需设置--base-radius-size:-999px;--capsule-radius-size:-999px;设置成可爱型,只需设置--base-radius-size:8px;--capsule-radius-size:999px;


@radius-4: calc(var(--base-radius-size, 0px) + 4px);
@radius-8: calc(var(--base-radius-size, 0px) + 8px);
@radius-12: calc(var(--base-radius-size, 0px) + 12px);
@radius-16: calc(var(--base-radius-size, 0px) + 16px);
@radius-999: calc(var(--base-radius-size, 0px) + 999px);

// 圆角 (按钮button、搜索search)采用如下圆角;
// 可以自适应变成胶囊型
@special-radius-4: calc(var(--capsule-radius-size, 0px) + 4px);
@special-radius-8: calc(var(--capsule-radius-size, 0px) + 8px);
@special-radius-12: calc(var(,--capsule-radius-size 0px) + 12px);
@special-radius-16: calc(var(--capsule-radius-size, 0px) + 16px);
@special-radius-999: calc(var(--capsule-radius-size, 0px) + 999px);


到这里切换圆角的功能已经实现了,但是让业务方去记忆不同的圆角值对应三种风格,比如设置可爱风需要设置--base-radius-size:8px;--capsule-radius-size:999px;

这会增加业务方的记忆负担,能不能继续优化,让设置更简单易用呢?我又探索了在 CSS 中使用布尔运算,让业务方通过传入0、1、2,组件内自动计算出需要使用的圆角值。

利用calc + var实现纯css布尔运算

         


三种风格的计算逻辑



逻辑延展,适应更多风格

这样的方式就大大简化了业务的使用负担,只需要根据接口返回的风格类型,将对应的0、1、2通过 CSS 变量传入组件库,就可使用不同的圆角风格,计算过程完全在组件内部。后续如果要调整规则,也只需要在组件中进行全局的修改即可。

4.3  图标风格切换方案 

目前常见的图标风格切换方式,主要是图标名称的切换。假如原有 50 个通用型风格的图标,现在分别新增 50 个潮流型和可爱型图标,对应不同的图标名称,换图标名就达到了换风格的目的。我的方案简单概括就是换字体,不换图标名称;由于小程序中对包体积有严格控制,所以能不增加包体积则最好;


在字体图标平台创建三套字体图标库,分别为通用型,潮流型和可爱型字体库;并分别上传对应风格的图标;按照通用型图标库为基准,修改新增字体库里的图标名称和 Unicode 编码,做到三套字体库中图标名称和 Unicode 编码一一对应相同;如下图,同一个删除图标,在三种风格的字体库中,下图标记的地方代表 Unicode 编码和图标名称,在三个字体库中要设置成一样的。将三套字体图标引入到小程序项目中,由于图标名称和 Unicode 编码一致,所以只需要引入三套字体的定义内容,具体的图标伪元素定义内容基本一致,无需新增。

上图是设置的关键,每个图标库中需对应设置成一样的值。

五、总结

主题色可以设置任意一种色值,图标可以三种风格互相切换,圆角也可以三种风格互相切换。这三中风格又可以互相搭配。微盟移动端组件库 Titian 采用 CSS 变量方式切换风格,其中主题色风格提供三个 CSS 变量:--theme-r、--theme-g、--theme-b 对应主题色的 RGBA 色值,字体图标提供一个 CSS 变量,--icon-family 来设置图标对应的字体库的名称,圆角风格提供两个 CSS 变量:--base-radius-size 和 --capsule-radius-size 来设置圆角的增量,后续又优化为使用 --s 来计算得到增量圆角。

通过以上几个简单的 CSS 变量,微盟移动端组件库 Titian 实现了,使用纯 CSS 方式,在运行时动态切换主题风格和自由搭配三种类型风格的能力,在小程序和 H5 中是完全通用的,体验完全一致。微盟移动端组件库 Titian 动态切换主题的能力,给使用方丰富的选择性,体现品牌调性的多样化。也兼顾了商家品牌个性化需求的灵活性,圆角与图标风格可以进行脱钩单独选择风格,一键配置,全店生效。以及在已定义的部分场景中也能与全局风格脱钩 (例如价格色与标签色),既有统一的品牌风格,又不失场景化的灵活表达。贴合用户心智,维持品牌认知。在赋能品牌的同时,开发者能够探索出无限可能。

目前微盟移动端组件库 Titian 已经完全开源,期待大家共同构建组件库生态,让Titian组件库更加易用好用。         


最后一次编辑于  2023-09-04  
点赞 1
收藏
评论
登录 后发表内容