前端换肤以及更换字体大小

引言

前端换肤,旨在更换web前端应用的主题,来满足用户在不同时期的实际需求。

技术原理

前端换肤的技术原理有很多种这里给大家介绍一种,css 变量 + 主题类型。就是通过不同的类名实现相同的 css 变量,但是其 css 变量的值又是各自实现的,之后在编写组件时全部将写死的值换成对应的 css 变量即可。

实现步骤

假设我们要实现 dark 和 day 两种不同主题。

1、定义 dark 主题 theme/dark/color.less

less 复制代码
@mainColor: #01305f;
@mainTextColor: #ffffff;
@mainBgColor: #012447;

//覆盖 第三方库主题色 例如 ant-design-vue
@primary-color: @mainColor;

以下代码中 关键代码是 在 .dark 类名下 @import 专属于 dark 的 color 以及定义专属于 dark 的 css 变量。注意 css 变量名保持 与 .day 统一。

重写第三方库

如果项目中恰好使用了第三方库可以参考第三方库的 less / scss 变量,以及 css 类名重写皮肤。

theme/dark/index.less

less 复制代码
.dark {
  @import "./color.less";
  --main-color: @mainColor;
  --main-text-color: @mainTextColor;
  --main-bg-color: @mainBgColor;
  // 重写第三方库className
  .ant-radio-button-wrapper {
    color: @mainTextColor;
    background-color: @mainBgColor;
  }
}

2、定义 day 主题 theme/day/color.less

less 复制代码
@mainColor: #ffffff;
@mainTextColor: black;
@mainBgColor: #f0f2f5;

//覆盖 第三方库主题色 例如 ant-design-vue
@primary-color: @mainColor;

theme/day/index.less

less 复制代码
.day {
  @import "./color.less";
  --main-color: @mainColor;
  --main-text-color: @mainTextColor;
  --main-bg-color: @mainBgColor;
  // 重写第三方库className
  .ant-radio-button-wrapper {
    color: @mainTextColor;
    background-color: @mainBgColor;
  }
}

内部库

上面的代码使用了 less 如果使用 css 可以参考以下方式

如果内部有多个项目需要换肤 或者多个组件库需要替换变量, 建议将 css 变量和皮肤打包成 npm 包,各个项目和组件库引用同一个 css npm 包即可。

css 复制代码
:root{
--day--main-color: #ffffff;
--day--main-text-color: black;
--day--main-bg-color: #f0f2f5;
--dark--main-color: #01305f;
--dark--main-text-color: #ffffff;
--dark--main-bg-color: #012447;
}
.dark {
  --main-color: var(-dark--main-color);
  --main-text-color: var(--dark--main-text-color);
  --main-bg-color: var(--dark--main-bg-color);
}
.day {
  --main-color: var(-day--main-color);
  --main-text-color: var(--day--main-text-color);
  --main-bg-color: var(--day--main-bg-color);
}

以上只给出了皮肤样式,字体样式结构原理是一样的就不赘述了。

使用

以 Vue 举例:

项目内所有的皮肤颜色和字体大小均使用 css 变量后 我们只需更换 最大容器元素的 皮肤类名 即可做到换肤。

vue 复制代码
<template>
  <div id="app" :class="[theme, fontSize]">
    <img src="./assets/logo.png" />
    <br />
    <a-radio-group :value="fontSize" @change="handleSizeChange">
      <a-radio-button value="large"> Large </a-radio-button>
      <a-radio-button value="middle"> Default </a-radio-button>
      <a-radio-button value="small"> Small </a-radio-button>
    </a-radio-group>
    <a-radio-group :value="theme" @change="handleThemeChange">
      <a-radio-button value="day"> Day </a-radio-button>
      <a-radio-button value="dark"> Dark </a-radio-button>
    </a-radio-group>
  </div>
</template>

<script>

export default {
  name: "App",
  components: {
    HelloWorld,
  },
  data() {
    return {
      theme: "day",
      fontSize: "middle",
    };
  },
  methods: {
    handleSizeChange(e) {
      this.fontSize = e.target.value;
    },
    handleThemeChange(e) {
      this.theme = e.target.value;
    },
  },
};
</script>

<style lang="less">
#app {
  height: 100%;
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: var(--main-text-color);
  background-color: var(--main-bg-color);
  font-size: var(--main-font-size);
}
</style>

其中

css 复制代码
#app{
  color: var(--main-text-color);
  background-color: var(--main-bg-color);
  font-size: var(--main-font-size);
}

为关键代码

后续所有样式代码用 css 变量替代即可。

其核心原理是:在不同皮肤类名下实现了相同名称的 css 变量,它们各自引用了各自的颜色和像素尺寸实现,当 css类名 改变时,类名内部实现的 css 变量 的值也同时改变了。

(完)

相关推荐
星光不问赶路人2 分钟前
Vue 3 对象监听与快照:ref 和 reactive 的关键差异
前端·vue.js
世界一刘先生2 分钟前
不引入 JSZip,自己写一个 ZIP 打包器:CRC32、中央目录与 UTF-8 文件名
前端
全栈项目管理程序猿2 分钟前
ArcGIS JS 基础教程(34):体元系列 - 等值面 VoxelIsosurface
前端·javascript
代码搬运媛4 分钟前
如何使用 @codemirror/view 库创建一个简单的代码编辑器
前端
huali6 分钟前
草稿该存在哪:per-session 是怎么成为共识的
前端·产品经理·产品
IPIPD8 分钟前
Proxifier规则为什么没有生效?从连接日志定位规则命中与DNS路径
前端
baiyunfan9 分钟前
微信小程序做 PDA 扫码出入库:库存并发控制与 4 个坑
前端
ZoeLandia9 分钟前
React6:组件通信
前端·react.js·typescript
爱勇宝9 分钟前
AI 都这么强了,咱们程序员以后还能干点啥?
前端·后端·程序员
FPGA小徐15 分钟前
【一生一芯 / PA】AM 核心文件逐行解析(上):从 start.S 到 gpu.c
前端·算法