携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情。
这是我的专栏《前端入门到进阶》,跟HullQin学前端,入门到进阶!带你进大厂!
背景
最近在研究微信官方的weui.css
,发现有些实现比较巧妙。比如Button的active
状态,它不是通过直接设置:active
时的颜色,而是在:active
时,叠加了一个透明遮罩层上去,使得按钮颜色颜色不一样。
而不是像Ant Design一样,分别定义了所有主色的常态
、active态
、hover态
。
此外,字节跳动的Arco Design也是通过CSS变量表示所有主色的各种状态,但它多嵌套了一层CSS颜色变量,这比Ant Design灵活性高一些:
为什么微信要这么做
其实在白天模式、暗夜模式,让用户感觉舒适的active状态
其实是不同的:
- 在白天模式,按钮颜色在
active状态
应该更暗; - 在暗夜模式,按钮颜色在
active状态
应该更亮。
如果某个颜色的白天、暗夜模式色号相同,那它的active状态
在白天、黑夜模式下一定不相同。
如果给所有的主色都指定active状态
色号,那么会有非常多的颜色值:白天模式普通状态色号、白天模式active状态色号、暗夜模式普通状态色号、暗夜模式active状态色号。后来微信又出现了新的模式:关怀模式,也会影响色号的值(对比度更大)。最终,这些色号常量将翻倍增加,设计师难以维护!
所以微信设计师就给active状态
设计了一套规则:白天模式就给元素叠加一个透明的暗的遮罩层表达active状态
,黑夜模式就给元素叠加一个透明的亮的遮罩层表达active状态
。这样,每个主色只需要维护一个普通状态
色号即可。
备注:这个做法可能不是微信首创的,可能其它优秀的组件库也是这么实现的,这里只是拿微信举个例子。
微信是怎么实现的
假如有个按钮,那么微信是如何通过叠加遮罩层实现active状态
的呢?
1. 定义白天、暗夜模式的遮罩层色号
首先,微信定义了1个「遮罩层色号」CSS变量,它会跟随当前白天/暗夜主题变化,这个CSS变量表示遮罩层的色号:
.wx-root,body {
--weui-BTN-ACTIVE-MASK: rgba(0, 0, 0, 0.1);
}
.wx-root[data-weui-theme='dark'],body[data-weui-theme='dark'] {
--weui-BTN-ACTIVE-MASK: rgba(255, 255, 255, 0.05);
}
@media (prefers-color-scheme:dark) {
.wx-root:not([data-weui-theme='light']),body:not([data-weui-theme='light']) {
--weui-BTN-ACTIVE-MASK: rgba(255, 255, 255, 0.05);
}
}
复制代码
这里微信写的比较复杂,其实是给前端开发者2种实现暗黑模式的方案:
- 网页主题可以跟随操作系统的白天/暗夜主题。这是通过媒体查询@media (prefers-color-scheme:dark)实现的。
- 网页主题可以通过Html标签里的
data-weui-theme
属性控制。这允许开发者在网页中放一个白天/暗夜模式的开关,网页的主题不再跟随操作系统,而是用户主动可控。
不得不承认,这个写法确实简短、精妙。
2. 给Button添加before伪元素
为了给Button元素增加一个透明的遮罩层,方法有很多,微信采用了精巧的纯CSS方案:before伪元素。
.weui-btn:before {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.1);
background-color: var(--weui-BTN-ACTIVE-MASK);
border-radius: 8px;
}
复制代码
在设置了content
后,会自动在Button元素前添加一个大小一模一样、形状一模一样的伪元素,该伪元素拥有透明的背景色,就实现了叠加遮罩层。
当然,这段样式没有设置content
,content
默认值是normal
,不会展示伪元素。
3. 在Button actice状态时展示伪元素
.weui-btn:not(.weui-btn_disabled):not(.weui-btn_loading):active:before,.weui-btn:not([disabled]):not(.weui-btn_loading):active:before {
content: "";
}
复制代码
只要在Button:active时,设置content
为""
就会展示伪元素,上面的遮罩层就出现了。
这个CSS写的很长,是为了防止disabled
的按钮或者loading
的按钮变成active
状态。
两种方案对比
方案 | 案例 | 优点 | 缺点 |
---|---|---|---|
维护所有主色的所有状态、所有模式的色号枚举值 | Ant Design, Arco Design | 设计师可以精心挑选和任意搭配,灵活性高 | 色号维护成本高 |
维护主色的色号枚举值,根据遮罩层计算其它状态和模式的色号 | WeUI | 各种状态的计算方式统一,维护成本低 | 色号模式比较固定 |
二者都是优秀的方案,大家可以根据需要决策。只是WeUI的实现方式令我眼前一亮,打破了我以前的认知(以为只能通过枚举所有色号值来表示Hover态、Active态),所以就分享给大家。
写在最后
我是HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,联系我,交个朋友),转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费无广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这2个专栏里分享:《教你做小游戏》、《极致用户体验》。