Tailwind Css 中使用 Element Plus 主题系统的方案与实现

前言

本篇文章主要讲解在 Tailwind Css 中配置 Element Plus 主题变量以统一视觉设计

本文也是《通俗易懂的中后台系统建设指南》系列的第九篇文章,该系列旨在告诉你如何来构建一个优秀的中后台管理系统

需求概括

上一篇文章中我们讲解了生成 Element Plus 主题色阶和动态切换主题色:一篇文章实现 Element Plus 色彩动态切换

Clean Admin 中使用 Tailwind Css 来编写大部分样式

如果你不知道 Tailwind Css ,应该看看这个:Tailwind Css 官网

Tailwind Css 预设了多套色彩方案,但为了保持整个系统的色调、视觉设计统一,我们希望在 Tailwind Css 中能够使用 Element Plus 的主题变量

比如编写一个盒子卡片样式,盒子边框颜色 border-el-border-light 和字体颜色 text-el-primary-500 都表示采用 Element Plus 主题变量

html 复制代码
    <div class="size-12 border border-solid border-el-border-light rounded-lg">
      <span class="text-el-primary-500">盒子</span>
    </div>

Clean Admin 目前停留在 tailwind 3.x 版本,后面配置都是基于此版本实现

Tailwind 主题与配置

Tailwind 文档有一篇文章介绍了 Tailwind 主题与配置,允许我们在 tailwind.config.js 中定制自己的主题

比如试着将 Element Plus 主题变量写入 Tailwind 主题配置

注意,这里使用的是 extend,意思是扩展 Tailwind 主题配置,而不改变原有的预设主题

js 复制代码
export default {
  theme: {
    extend: {
      colors: {
        'el-primary': {
          100: 'var(--el-primary-100)',
          200: 'var(--el-primary-200)',
        },
      },
    },
  },
}

这样手动配置确实有效,但缺乏灵活性,且工作量还是比较大的,我们的方案是通过函数来生成符合要求的配置

生成色阶函数

Clean Admin 中有一个 theme 文件夹,在这里新建一个 tailwind 文件,用于处理 Tailwind 相关配置

上篇文章我们已经生成了 1 ~ 9 的 el-color-primary 色阶

根据这段色阶,现在需要写一个函数来生成符合 Tailwind 配置格式的色阶对象

比如,一个 generateElPrimaryScale 函数

ts 复制代码
/** 颜色类型 */
type ElColorType = 'primary' | 'success' | 'warning' | 'danger' | 'info';

/** Element Plus 主题色权重 */
const EL_PRIMARY_COLOR_WEIGHT = [100, 200, 300, 400, 500, 600, 700, 800, 900];

/**
 * 生成 Element Plus 主色、辅助色-色阶(primary、success、warning、danger、info)
 * @param colorType 主色、辅助色类型
 * @param weights 权重
 * @returns 颜色色阶
 */
export function generateElPrimaryScale(
  colorType: ElColorType = 'primary',
  weights: number[],
): Record<number | string, string> {
  const colorVariableScale: Record<number | string, string> = {};

  colorVariableScale.DEFAULT = `var(--el-color-${colorType})`;

  colorVariableScale['dark-200'] = `var(--el-color-${colorType}-dark-2)`;

  weights.forEach((weight) => {
    colorVariableScale[weight] = `var(--el-color-${colorType}-light-${weight / 100})`;
  });

  return colorVariableScale;
}

/** Tailwind 主题配置 */
export const tailwindThemeConfig: Config['theme'] = {
  extend: {
    colors: {
      /** 主题色 */
      'el-primary': generateElPrimaryScale('primary', EL_PRIMARY_COLOR_WEIGHT),
    }
  },
};

这里的 generateElPrimaryScale 函数,主要用于生成 Element Plus 主色、辅助色等色阶

EL_PRIMARY_COLOR_WEIGHT 是主颜色的权重,每个色梯都对应着一个 Element Plus Css 变量

el-primary 是样式前缀,比如要调用主颜色的 300 色阶,就可以写 text-el-primary-300,语法是 text-el-primary-[权重]

ts 复制代码
  console.log(generateElPrimaryScale('primary', EL_PRIMARY_COLOR_WEIGHT));

打印这个函数的返回值,输出的结构如下

现在,还差最后一步:把 tailwindThemeConfig 配置到 tailwind.config.js

tailwind.config.js 是 Tailwind Css 的配置文件,一般放在根目录下

js 复制代码
import { tailwindThemeConfig } from './src/theme/tailwind';

/** @type {import('tailwindcss').Config} */
export default {
  theme: {
    ...tailwindThemeConfig,
  },
};

截止到这一步,配置工作已经完成,测试一下 Tailwind Css 中是否生效

  1. 根据 IDE 中 Tailwind 插件的提示,检查是否生效(下图效果)
  2. 使用 Tailwind Css 方式写入 Element Plus 主题变量,观察在浏览器的样式效果

注意,这里默认你在 VSCode、Cursor 中安装了 Tailwind 插件,能够自动提示

比如我们希望把一段文本颜色设置为默认主题色,可以这样做

其他辅助色

Element Plus 除了主颜色外,还存在一些辅助色,比如 成功色(Success)、警告色(Warning)、危险色(Danger)、信息色(Info)

和上面的配置操作一样,我们已经有了色阶函数,只需要把剩下颜色都配置到 tailwindThemeConfig 中即可

Clean Admin 中针对主颜色分了 9 个色阶,辅助色(Success、Warning、Danger、Info)等则根据 Element Plus 默认分为了 5 个色阶

ts 复制代码
/** Element Plus 辅助色权重 */
const EL_ASSISTANT_COLOR_WEIGHT = [300, 500, 700, 800, 900];

/** Tailwind 主题配置 */
export const tailwindThemeConfig: Config['theme'] = {
  extend: {
    colors: {
      //...
      /** 成功色 */
      'el-success': generateElPrimaryScale('success', EL_ASSISTANT_COLOR_WEIGHT),
      /** 警告色 */
      'el-warning': generateElPrimaryScale('warning', EL_ASSISTANT_COLOR_WEIGHT),
      /** 危险色 */
      'el-danger': generateElPrimaryScale('danger', EL_ASSISTANT_COLOR_WEIGHT),
      /** 信息色 */
      'el-info': generateElPrimaryScale('info', EL_ASSISTANT_COLOR_WEIGHT),    }
  },
};

Clean Admin 中关于此部分的代码:点击查看

Element Plus 中性色配置

翻开 Element Plus 官网的色彩篇

Element Plus 主题系统中除了主颜色、辅助颜色,还提供了中性色,包括文本、边框、填充、背景等

前面部分给出的色阶函数,只适用于主颜色、辅助颜色,中性色的梯度有些不同,比如不是单纯用色阶数字来表示层级

这里再写一个针对中性色的函数

ts 复制代码
/**
 * 生成 Element Plus 中性色-色阶
 * @param colorType 中性色类型(border、bg、fill、text...)
 * @param weights 权重列表
 * @param hasDefault 是否包含默认值
 * @returns 颜色色阶
 */
export function generateElThemeScale(
  colorType: string,
  weights: number[] | string[],
  hasDefault: boolean = true,
): Record<number | string, string> {
  const colorVariableScale: Record<number | string, string> = {};

  hasDefault && (colorVariableScale.DEFAULT = `var(--el-${colorType}-color)`);

  weights.forEach((weight) => {
    colorVariableScale[weight] = `var(--el-${colorType}-color-${weight})`;
  });

  return colorVariableScale;
}

这个色阶函数中有一个参数 hasDefault ,默认为 true,用于决定是否包含默认值 DEFAULT,像文本色值,就不存在 --el-text-color 变量

通过在谷歌浏览器开发者工具中找到 Element Plus 的相关 Css 变量及权重,比如文本和边框

ts 复制代码
/** Element Plus 文本权重 */
export const EL_TEXT_WEIGHT = ['primary', 'regular', 'secondary', 'placeholder', 'disabled'];

/** Element Plus 边框权重 */
export const EL_BORDER_WEIGHT = ['darker', 'dark', 'light', 'lighter', 'extra-light'];

generateElThemeScale 函数生成中性色的色阶,然后在 tailwindThemeConfig 中配置

ts 复制代码
/** Tailwind 主题配置 */
export const tailwindThemeConfig: Config['theme'] = {
  extend: {
    //...
    textColor: {
      /** 文本色阶 */
      'el-text': generateElThemeScale('text', EL_TEXT_WEIGHT, false),
    },
    borderColor: {
      /** 边框色阶 */
      'el-border': generateElThemeScale('border', EL_BORDER_WEIGHT),
    },
  },
};

假设在一个 div 上写入边框和文本颜色

html 复制代码
    <div class="size-12 border border-solid border-el-border rounded-lg">
      <span class="text-el-text-primary">盒子</span>
    </div>

最后

写到这里,我们已经基本实现了在使用 Tailwind Css 中使用 Element Plus 变量的需求

可以在 vue-clean-admin/theme 文件夹中查看完整代码

参考资料

了解更多

系列专栏地址:GitHub 博客 | 掘金专栏 | 思否专栏

实战项目:vue-clean-admin

专栏往期回顾:

  1. 收下这份 Vue + TS + Vite 中后台系统搭建指南,从此不再害怕建项目
  2. 中后台开发必修课:Vue 项目中 Pinia 与 Router 完全攻略
  3. 用了这些 Vite 配置技巧,同事都以为我开挂了
  4. 受够了团队代码风格不统一?7千字教你从零搭建代码规范体系
  5. 开发者必看!在团队中我是这样实现 Git 提交规范化的
  6. 告别繁琐!Vue3 组合式函数解锁 Echarts 封装新姿势
  7. 彻底搞懂面包屑,手把手封装一个 Vue3 面包屑导航组件
  8. 一篇文章实现 Element Plus 动态切换主题色

交流讨论

文章如有错误或需要改进之处,欢迎指正

相关推荐
山有木兮木有枝_3 分钟前
从代码到创作:探索AI图片生成的神奇世界
前端·coze
言兴14 分钟前
秋招面试---性能优化(良子大胃袋)
前端·javascript·面试
WebInfra1 小时前
Rspack 1.5 发布:十大新特性速览
前端·javascript·github
雾恋2 小时前
我用 trae 写了一个菜谱小程序(灶搭子)
前端·javascript·uni-app
烛阴2 小时前
TypeScript 中的 `&` 运算符:从入门、踩坑到最佳实践
前端·javascript·typescript
Java 码农3 小时前
nodejs koa留言板案例开发
前端·javascript·npm·node.js
ZhuAiQuan4 小时前
[electron]开发环境驱动识别失败
前端·javascript·electron
nyf_unknown4 小时前
(vue)将dify和ragflow页面嵌入到vue3项目
前端·javascript·vue.js
胡gh4 小时前
浏览器:我要用缓存!服务器:你缓存过期了!怎么把数据挽留住,这是个问题。
前端·面试·node.js
你挚爱的强哥4 小时前
SCSS上传图片占位区域样式
前端·css·scss