毕业设计做网站 答辩会问什么问题,学做川菜的网站,丰台网站开发,广东省网站备案要多久动态调整系统主题色(4): CssVar 与 Variant 方案的探索
动态调整系统主题色(4): CssVar 与 Variant 方案的探索 前言方案的介绍与比较 CssVar (CSS 变量方案)CSS 变量方案与 tailwindcss 的结合Variant 方案 2种方案在小程序上的示例之前的几篇
前言
这篇已经是动态调整系统…
动态调整系统主题色(4): CssVar 与 Variant 方案的探索
动态调整系统主题色(4): CssVar 与 Variant 方案的探索 前言方案的介绍与比较 CssVar (CSS 变量方案)CSS 变量方案与 tailwindcss 的结合Variant 方案 2种方案在小程序上的示例之前的几篇
前言
这篇已经是动态调整系统主题色的第四篇了转眼距离第一篇发布已经过去了2年的时间。随着时间的流逝对技术的理解也在不断的进步方案也在不断的完善和推陈出新本篇文章就是在探讨系统主题色的 2 方案: CssVar 和 Variant。
方案的介绍与比较
假如你没有看前面三篇文章的话初看到这 2 个词可能不能直观的知道它们是什么意思下面我先简单介绍一下它们是什么以及它们的原理。
CssVar (CSS 变量方案)
这个方案很简单大意就是我们预先定义出有多少种颜色会被使用贯穿整个设计规范。然后把它们定义成 CSS 变量然后再通过更改 CSS 变量的值去改变整个主题。
比如我们可以这样去定义:
:root{--prism-background: #f4f4f4;
}
/*暗色*/
html.dark{--prism-background: #181818;
}body{background-color: var(--prism-background);
}这种方式把其他的主题定义在了 :root/html 选择器之下本质上是在利用选择器的优先级去覆盖原先定义CSS变量的值从而达到切换的效果。这个方案非常的通用你看到的很多的组件库都是使用这个方案的比如 element-plus / vant 等等antd 不是
CSS变量会从它被使用的地方从自己递归向上去寻找定义所以我们想覆盖定义在 :root 里定义的变量可以直接在它被使用到的地方再定义一个值用来替换达到覆盖的效果。
所以我们可以去封装一个组件 ThemeProvider里面就定义一个 div 元素包裹一个插槽再把CSS变量动态设置在这个元素上从而达到切换插槽内局部CSS变量的效果。(是不是感觉似曾相识)
CSS 变量方案与 tailwindcss 的结合
当然CSS变量方案和 tailwindcss 能够得到非常好的结合我们只需要预先在tailwind.config.js 的 theme 中预先去扩展定义变量即可。
不过和上面那种方式有些不同这里我们定义的 CSS 变量是字符串而不是直接的颜色这是为了后续能和透明度做一个动态的运算。比如我们这里有多个主题分别为 light(默认),deep,dark,fantasy我们可以这样定义: enum ModeEnum {light light,deep deep,dark dark,fantasy fantasy}// 要完全的动态可配置可以把这些值保存在服务端动态获取// 然后在前端写个页面用用取色器这个组件去设置颜色保存进数据库// 这样就不需要前端写死变量了从而达到更灵活的配置效果const cssVarsMap: RecordModeEnum, Recordstring, string {light: {--ice-color-base: 191, 219, 254,--ice-color-primary: 30, 58, 138,--ice-color-primary-content: 255, 255, 255},deep: {--ice-color-base: 125, 211, 252,--ice-color-primary: 79, 70, 229,--ice-color-primary-content: 255, 255, 255},dark: {--ice-color-base: 2, 132, 199,--ice-color-primary: 165, 180, 252,--ice-color-primary-content: 0,0,0},fantasy: {--ice-color-base: 8, 47, 73,--ice-color-primary: 224, 231, 255,--ice-color-primary-content: 0,0,0}}然后把这些变量的值动态设置在 html 上或者传入 ThemeProvider 中就能达到切换的目的了。
简单的配置如下:
/** type {import(tailwindcss).Config} */
module.exports {theme: {extend: {colors: {primary: rgba(var(--ice-color-primary), alpha-value),primary-content:rgba(var(--ice-color-primary-content), alpha-value),base: rgba(var(--ice-color-base), alpha-value)}}},
}同时由于我们定义的值是字符串我们就可以利用这一点去自由的组合使用 rgba 构造函数来决定它的透明度了。即利用CSS变量字符串的特性组合出, rgba(r,g,b,a) 的效果这样写法上就非常自由了同一个主题色你可以写出 text-primary 直接使用 primary 色也可以写出 text-primary/50 这样 50% 透明度的 primary 色。(这就是 alpha-value 占位符的目的)
这样我们定义组件的时候就可以用一个类名去动态引用变量了:
templatebuttonclassbg-primary text-primary-contentslot/slot/button
/template这个组件背景主色文字为主色的 content 色。
Variant 方案
不知道你有没有注意过在 tailwindcss 自带的暗黑模式切换中它使用的写法是 text-gray-800 dark:text-gray-200。
这种的语义上非常的直观看到它你就知道这个元素 color 默认情况下是 text-gray-800暗黑模式下color是 text-gray-200。
同样它的生成也是在利用选择器/媒体选择器的优先级去覆盖大体的原理如下:
border-white {--tw-border-opacity: 1;border-color: rgb(255 255 255 / var(--tw-border-opacity));
}:is(.dark .dark:border-slate-800) {--tw-border-opacity: 1;border-color: rgb(30 41 59 / var(--tw-border-opacity));
}其中这个 dark: 打头的条件就被称为 Variant我们可以根据自己的需求创建很多个 Variant 来定义并生成不同的 CSS 区块。同样我们可以去基于这种方法去扩展我们的主题。
比如我们这里我们还是有多个主题分别为 light(默认),deep,dark,fantasy我们可以这样定义:
const plugin require(tailwindcss/plugin)/** type {import(tailwindcss).Config} */
module.exports {// 默认会添加 dark 的 Variant 和 .dark 的 css 生成块darkMode: class,plugins: [plugin(function ({ addVariant, addBase }) {addVariant(deep, :is(.deep ))addVariant(fantasy, :is(.fantasy ))}),],
}这样我们像上面同样定义一个 button 组件就要这样写: buttonclassbg-pink-900 deep:bg-pink-600 dark:bg-pink-300 fantasy:bg-pink-100 text-white deep:text-gray-300 dark:text-gray-600 fantasy:text-gray-900slot/slot/button这样显然是非常冗长的即使它还存在着一些可读性但是还是瑜不掩瑕而且使用 apply 去提取的话也是容易出错的。
而且还有一个致命的问题这种方案每多一个主题就要加一个 Variant这显然非常的不灵活的。所以说在不确定主题数量的情况下这个方案是个灾难。主题色显然不是Variant适合的场景。
这个方案可能只适合暗黑模式这个特殊的场景。但是 CssVar 方案也能适配 暗黑模式 的。
所以主题色方案还是选择 CssVar 就行了。
2种方案在小程序上的示例
#小程序://tailwind/RvdAJVby6DXgZpa
复制到微信后打开这里就不放小程序码了省的被掘金判断是推广的文章。
或者微信搜索 tailwind 小程序进入查看效果。
之前的几篇 动态调整web系统主题? 看这一篇就够了 动态调整web主题(2) 萃取篇 动态调整web主题(3): 基于tailwindcss插件的主题色生成方案