// windi.config.js
function withOpacityValue(variable) {
return val => {
if (val.opacityValue === undefined) {
return `rgb(var(${variable}))`
return `rgb(var(${variable}) / ${val.opacityValue})`
export default defineConfig({
theme: {
extend: {
colors: {
primary: {
extralight: withOpacityValue('--color-primary-extralight'),
light: withOpacityValue('--color-primary-light'),
medium: withOpacityValue('--color-primary-medium'),
DEFAULT: withOpacityValue('--color-primary'),
dark: withOpacityValue('--color-primary-dark'),
如此一来,每当使用 primary
颜色时,WindiCSS 都会调用函数来生成样式,通过对 opacityValue
的判断来实现对透明度语法的支持。
SCSS 生成 CSS 变量
显然,如果手动为 light
extralight
等颜色变种指定颜色值是不现实的,况且现在需要用 R G B 三个数字来表示颜色,编辑器没有高亮,不直观,也会导致维护困难。
这时候SCSS就能派上用场了!SCSS提供了基础的CSS数据类型,判断、遍历语法,同时也提供了海量的工具函数(例如 red()
blue()
green()
等用于通道分离,mix()
用于颜色混合)
首先来实现一个工具函数,将传入的十六进制颜色转换成 R G B 三个数字的形式
@function getColorValue($color) {
@return #{red($color)} #{green($color)} #{blue($color)};
/* getColorValue(#2196f3) -> 33 150 243 */
我预想中的情况是——只要给一个 primary
的基础色,SCSS就能帮我把 light
extralight
等颜色变种都生成出来。我是用 mix
方法来实现:
@mixin spread-theme-map($map: ()) {
@each $key, $value in $map {
#{"--"+$key}: $value;
@function theme-primary-map($primary-color: #2196f3) {
@return (
color-primary-dark: getColorValue(mix($primary-color, black, 30%)),
color-primary: getColorValue($primary-color),
color-primary-medium: getColorValue(mix($primary-color, white, 70%)),
color-primary-light: getColorValue(mix($primary-color, white, 35%)),
color-primary-extralight: getColorValue(mix($primary-color, white, 15%))
/* spread-theme-map(theme-primary-map(#2196f3)) */
这样,就能针对某一个颜色生成对应的系列颜色属性了。接下来,只需要定义一个数组,把需要的主题色放进去,跑个循环即可(从 Material Design 的文档里随便挑了几个养眼的颜色):
$themeColorList: (
#2196f3,
#f44336,
#9c27b0,
#4caf50,
#3f51b5,
#795548,
#607d8b,
#009688
@for $i from 1 through length($themeColorList) {
$color: nth($themeColorList, $i);
.theme-#{$i} {
@include spread-theme-map(theme-primary-map($color));
在VSCode中,看起来是这样的:
const randomThemeColorIndex = useState('randomThemeColorIndex', () =>
Math.floor(Math.random() * themeColorList.length) + 1
useHead({
bodyAttrs: {
class: 'theme-' + randomThemeColorIndex.value,
分享到 Twitter
#CSS #Vue.js #代码片段 #前端 首页 • 代码 • SCSS+WindiCSS实现主题色切换