一键换肤的实现

2021-03-23  本文已影响0人  雷布斯基

在网站迭代升级时,经常会收到更换网站配色的需求,或者提供入口,让用户自己选择页面的配色主题。
该怎么去实现这种需求呢?
我们先看看antd里面,是用的什么方式来实现的:

antd 的样式使用了 Less 作为开发语言,并定义了一系列全局/组件的样式变量,你可以根据需求进行相应调整。
...
原理上是使用 less 提供的 modifyVars 的方式进行覆盖变量,可以在本地运行 例子 查看定制效果。下面将针对不同的场景提供一些常用的定制方式。

有两种方式实现定制主题:

// webpack.config.js
module.exports = {
  rules: [{
    test: /\.less$/,
    use: [{
      loader: 'style-loader',
    }, {
      loader: 'css-loader', // translates CSS into CommonJS
    }, {
      loader: 'less-loader', // compiles Less to CSS
+     options: {
+       lessOptions: { // 如果使用less-loader@5,请移除 lessOptions 这一级直接配置选项。
+         modifyVars: {
+           'primary-color': '#1DA57A',
+           'link-color': '#1DA57A',
+           'border-radius-base': '2px',
+         },
+         javascriptEnabled: true,
+       },
+     },
    }],
    // ...other rules
  }],
  // ...other config
}

这种方式能直接在编译代码时,直接替换对应的颜色值,但是不支持动态更换主题色。

"theme": {
  "primary-color": "#1DA57A",
},

这种方式依赖umi,而且和webpack的一样,不支持动态修改颜色值。

@import '~antd/lib/style/themes/default.less';
@import '~antd/dist/antd.less'; // 引入官方提供的 less 样式入口文件
@import 'your-theme-file.less'; // 用于覆盖上面定义的变量

这种方式比较灵活,没有额外的依赖。如果需要添加动态更换主题色,可以考虑在切换主题色选项后,给body上添加不同的className,实现不同主题色的展示。甚至可以通过动态加载css文件的方式进行样式的覆盖,不过要注意样式的优先级:

/**
 * 动态加载CSS
 * @param {string} url 样式地址
 */
function dynamicLoadCss(url) {
  const head = document.getElementsByTagName('head')[0]
  const link = document.createElement('link')
  link.type = 'text/css'
  link.rel = 'stylesheet'
  link.href = url
  head.appendChild(link)
}

css variables

除了上述的一些方法,还可以尝试使用css variablescss variables 的基本概念和语法可以通过 Using CSS custom properties (variables) 进行了解。

: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);
  }

修改主题时,直接操作颜色变量。

const bodyStyles = document.body.style;
bodyStyles.setProperty('--primary-color', 'red');
bodyStyles.setProperty('--tertiary-color', 'yellow');

但该方案有一些兼容性的问题,使用前也需要进行评估:caniuse

image.png
上一篇下一篇

猜你喜欢

热点阅读