前言
提示:使用 css/less 动态更换主题色(换肤功能),方法共通,不限制技术栈:
其实在日常项目开发中经常会遇到有些用户想要一些自定义的的主题色来满足不同的视觉需求,这时候就需要通过动态更改主题色来实现预期的效果;
一、CSS中原生变量"--"和var()
示例:开始之前先稍微了解一下变量"--"和var(),在动态改变主题色中会经常用到这两个变量
@表示我们定义的的变量名称
css中原生的变量定义语法是:--@
例如定义一个边框颜色变量: --border-color: #D9EEE2;
css中变量使用语法是:var(--@)
例如使用定义的边框颜色变量:border: 0.1rem solid var(--border-color);
二、使用步骤
1、自定义样式变量,定义css方法(可以定义多个css样式)
要注意的是不管定义了几个主题色,都要确保定义的变量名保持一致。
javascript
// theme.less
/*
*这里为我们自定义主题色,可以根据自己的需求定义多组样式
*
*/
// 主题类型定义
:root {
// 背景色
--bg-color: #D9EEE2;
--border-color: #D9EEE2;
// 很多图标、border都用这个颜色
--icon-color: #108372;
// 按钮背景色
--button-bg-color: var(--dominant-color);
// 选中字体和图表颜色
--active-font-color: #037181;
// hover字体和图表颜色
--hover-font-color: var(--dominant-color);
// logo
--logo: url('你的图片路径') no-repeat center center;
...
...
...
}
/* 这里假设为我们自定义的主题 */
:root[theme = 'defined'] {
// 背景色
--bg-color: pink;
--border-color: pink;
// 很多图标、border都用这个颜色
--icon-color: pink;
// 按钮背景色
--button-bg-color: pink;
// 选中字体和图表颜色
--active-font-color: pink;
// hover字体和图表颜色
--hover-font-color: var(--dominant-color);
// logo
--logo: url('你的图片路径') no-repeat center center;
...
...
...
}
2、使用已定义的变量
使用其实很简单,只要根据主题色动态改变的地方通过var()引用已经定义的样式变量就可以;
javascript
/*
* 这里举个简单的例子 child.less(这里就是项目中引用的css文件)
*/
.root{
.main{
background:var(--bg-color);
border:1px solid var(--border-color);
...
}
...
}
3、用户操作,切换对应的主题
通过设置属性自动匹配选择颜色主题,会修改对应的样式;
1)、首先你跟据需求在特定位置定义好主题切换功能键;
这里是定义的结构体,仅作参考(你可以根据自己项目的框架使用对应的组件都是ok的,没啥特殊要求)
javascript
<div className={styles.root}>
<Dropdown overlay={menu} placement="bottomCenter">
<div>
<i className="iconfont icon-them" />
<span>主题</span>
</div>
</Dropdown>
</div>
这里是菜单的主题曲部分,切换全靠它了;
javascript
// 这里的items就是你要定义的主题的种类,没有key代表一个主题色标识
const menu = (
<Menu
selectable
selectedKeys={theme}
onClick={setThemeFun}
items={[
{
label: '默认色',
key: 'default',
},
{
label: '自定义',
key: 'defined',
},
]}
/>
);
2)、然后通过对应的方法设置对应的的主题色;
javascript
/*主题色选择后的回调*/
const setThemeFun =(e)=>{
// 这里其实就是将主题表示存在state里,在menu中展示, 默认 const [theme, setTheme] = useState(['default']);
setTheme([e.key]);
//通过修改属性,会用对应的样式
document.documentElement.setAttribute('theme', e.key);
}
这里建议把切换主题色封装到一个单独的组件,便于维护处理
切记:初始化时要个给一个默认值,这里就不做过多赘述了
4、特殊处理
1)本地存取主题色
其实用户没有的要求的话,一般都是主题的存储本地,可以通过localStorage实现
javascript
// 在你需要的时候存在来
localStorage.setItem('theme', e.key);
//特定情况取出来使用就可以了
const defaultTheme = localStorage.getItem('theme');
if (defaultTheme) {
setTheme([defaultTheme]);
document.documentElement.setAttribute('theme', defaultTheme);
}
注:本地存储小科普
生存期
localStorage理论上来说是永久有效的,即不主动清空的话就不会消失,即使保存的数据超出了浏览器所规定的大小,也不会把旧数据清空而只会报错。但需要注意的是,在移动设备上的浏览器或各Native App用到的WebView里,localStorage都是不可靠的,可能会因为各种原因(比如说退出App、网络切换、内存不足等原因)被清空。
sessionStorage的生存期顾名思义,类似于session,只要关闭浏览器(也包括浏览器的标签页),就会被清空。由于sessionStorage的生存期太短,因此应用场景很有限,但从另一方面来看,不容易出现异常情况,比较可靠。
2)接口存取主题色
这个就需要跟产品和后端确认好方案,是否绑定用户或者设备,通过对应的接口实现主题色存取,原理和上述本地存储大差不差,具体根据需求走就行了
总结
以上是使用纯CSS控件切换主题颜色或通过单击更改背景颜色,这个个人感觉可能前期样式定义稍微繁琐一点,其他都还可,相对来说易上手方便操作,关键是简单,不过要注意以下几点:
1、需求确定好是否需要主题色切换;
2、需要的话对一些字体图标的定义要跟ui和pd沟通好,构建好对应的iconfont工程,方便使用,因为你要清楚如果单纯使用图片,那切换主题色,变量定义就会很繁琐,一句话怎么方便怎么好维护就怎么来;
3、一定要确保主题的定义的变量保持一致......
......