前言
由于公司客户众多,有其偏好的主题色,要求我们的产品统一成他们内部的主题色。鉴于此想法,就有了自定义主题颜色的需求。且为了能节约研发和测试的成本,节省一大串流程,希望能一键替换,无需修改代码,无需重新打包。 目前的技术栈是:vue + iview/bsview + less,基于ivew封装的bsview采用的是内部ui设计,有其独特的配色。
1. 替换样式文件
将组件库和项目本身的颜色变量配置抽取出来,只需更改这些文件即可。
- npm包
修改webpack配置,将颜色单独打成一个包,后期需要替换颜色的话,只需更新该包。
问题是现在前后端没有完全分离,前端打完的包是jar包形式,无法替换npm包。
- 整个css文件
修改颜色变量文件,重新打包,在jar外层直接替换样式文件。
2. js 内联样式
itemStyle() {
let style = {};
if (this.hasParentSubmenu && this.mode !== "horizontal") {
style.paddingLeft =
43 + (this.parentSubmenuNum - 1) * 24 + "px";
}
if (this.active && this.$IVIEW && this.$IVIEW.themeColor) {
style.color = this.$IVIEW.themeColor;
style.background = this.mix(
this.$IVIEW.themeColor,
"#ffffff",
0.9
);
style.borderColor = this.$IVIEW.themeColor;
}
return style;
}
利:
- 定义主题颜色,按需修改即可,思路清晰。
弊:
- 逐个修改,若要全范围修改,工作量大;
- 代码看起来很挫;
- js无法修改:hover等伪元素/伪类的样式。
**onmouseover/onmouseout ?
3. 全css-in-js的Styled component
github.com/styled-comp… medium.com/maestral-so…
import styled from 'vue-styled-components';
const btnProps = { primary: Boolean };
const StyledButton = styled('button', btnProps)`
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
background: ${props => props.primary ? 'palevioletred' : 'white'};
color: ${props => props.primary ? 'white' : 'palevioletred'};
`;
export default StyledButton;
<styled-button>Normal</styled-button>
<styled-button primary>Primary</styled-button>
可解决,代价是全盘重写。
4. element-ui 换肤
基于有特定的配色方案,可通过js形成新的配色方案,查找所有的主题相关颜色,并替换。 example:elementui.github.io/theme-chalk… www.cnblogs.com/rogerwu/p/9…
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */
但我们的配色方案没有遵循一定的规则,无法精确查找与替换。
5. css variables
developer.mozilla.org/zh-CN/docs/… stackoverflow.com/questions/4…
<template
<app-main></app-main>
<app-sidebar></app-sidebar>
...
</template>
<style>
:root{
--primary-color: #C5C5C5!important;
--secondary-color: #6C7478!important;
--tertiary-color: #FFFFFF!important;
--success-color: #80b855!important;
--warning-color: #eaca44!important;
--error-color: #ef4d4d!important;
}
/* Theming */
header{
background-color: var(--primary-color);
}
div{
color: var(--tetriary-colory);
}
...
/* END */
</style>
<script>
import axios from 'axios' /* all your imports etc. */
export default{
data(){
},
methods: {
axios.post(`http://localhost:8080/foo`).then(function (response){
let bodyStyles = document.body.style;
bodyStyles.setProperty('--primary-color', response.colors[0]);
bodyStyles.setProperty('--tertiary-color', response.colors[1]);
...
}
}
}
</script>
利:
- css新特性,直接在css中读取js变量,可替换less变量,简便快捷,全面彻底。
弊:
- 有浏览器兼容性问题,ie不支持。(那就打个补丁吧,css-vars-ponyfill)
- 无法与less结合。由于css variables要在browser才能执行,在less预编译过程中,识别不了var(),因此,在使用到less function的情况下,无法满足需求。而我们目前的项目和组件库都用到了less,
在不替换less的情况下,除非一一将报错的less function替换成原生的css(范围未知,是否能都找到对应的也未知)。
既然****less function 会导致报错,那能不能尝试避开呢?
** 在iview的颜色处理中主要用到了tint/shade/fade这三个less function去处理,目前对于这些小细节的处理还不完善,主要是hover/focus状态的细微变化。
- js
采用css预处理器(less/sass)那一套mix颜色的方法,从一个主题色计算得出一系列加深或减淡的颜色。再通过定义多个var的方式,在css中引用。 利:浏览器兼容性没有问题。 弊:由于主题颜色的传入是在组件库外部,无法在组件库中统一处理,要在需主题定制的各项目中逐一处理。
- 原生css
采用原生css的hsl/hsla模仿加深/减淡颜色的逻辑。 stackoverflow.com/questions/1…
:root {
--link-color-h: 211;
--link-color-s: 100%;
--link-color-l: 50%;
--link-color-hsl: var(--link-color-h), var(--link-color-s), var(--link-color-l);
--link-color: hsl(var(--link-color-hsl));
--link-color-10: hsla(var(--link-color-hsl), .1);
--link-color-20: hsla(var(--link-color-hsl), .2);
--link-color-30: hsla(var(--link-color-hsl), .3);
--link-color-40: hsla(var(--link-color-hsl), .4);
--link-color-50: hsla(var(--link-color-hsl), .5);
--link-color-60: hsla(var(--link-color-hsl), .6);
--link-color-70: hsla(var(--link-color-hsl), .7);
--link-color-80: hsla(var(--link-color-hsl), .8);
--link-color-90: hsla(var(--link-color-hsl), .9);
--link-color-warm: hsl(calc(var(--link-color-h) + 80), var(--link-color-s), var(--link-color-l));
--link-color-cold: hsl(calc(var(--link-color-h) - 80), var(--link-color-s), var(--link-color-l));
--link-color-low: hsl(var(--link-color-h), calc(var(--link-color-s) / 2), var(--link-color-l));
--link-color-lowest: hsl(var(--link-color-h), calc(var(--link-color-s) / 4), var(--link-color-l));
--link-color-light: hsl(var(--link-color-h), var(--link-color-s), calc(var(--link-color-l) / .9));
--link-color-dark: hsl(var(--link-color-h), var(--link-color-s), calc(var(--link-color-l) * .9));
}
利:
- 可以在组件库中统一处理。
弊: