Skip to content
霞露小伙 — HfWang
On this page

css 变量实现主题切换

WARNING

这里是记录一下怎么使用纯 css 使用主题切换,如果想结合 less / scss, 可以看我另一篇文章 实现系统主题切换功能

  • 实战记录: 可以使用我的 create-whf 脚手架创建完整的 vue3 项目,里面已经内置了主题切换功能

gogogo

从头开始实现

shell
pnpm create vite
# 选择 vue3 + ts

src 下新建以下目录

- src
    - hooks
        - useTheme.ts
    - theme
        - index.ts
        - theme-default.ts
        - theme-blue.ts
        - types.ts
    - assets
        - global.css
    - App.vue
    - main.ts

定义主题

ts
// theme/types.ts
export type Theme = Record<string, string>
export type Themes = Record<ThemeType, Theme>[]
export type ThemeType = 'default' | 'blue'

// theme/index.ts
import type { Theme } from './types'
import defaultTheme from './default'
import blueTheme from './blue'

const themes = {
    default: defaultTheme,
    blue: blueTheme
} as Themes

export default themes


// theme/theme-default.ts
export default {
    primaryColor: 'yellow',
    activeTextColor: 'orange'
}

// theme/theme-blue.ts
export default {
    primaryColor: 'skyBlue',
    activeTextColor: 'green'
}

封装自定义 hook

ts
// hooks/useTheme.ts
import { ref } from 'vite'
import type { ThemeType } from '@/theme/types'
import themes from '@/theme'

type LocalThemeType = ThemeType | null
const THEME_KEY = 'sys-theme'

const useTheme = () => {
    const theme = ref<ThemeType>(
        localStorage.getItem(THEME_KEY) as LocalThemeType || 'default'
    )

    const setTheme = (type: ThemeType) => {
        const html = document.getElementByTagName('html')[0] as HTMLHtmlElement

        themes[type].entries(([key, value]) => {
            html.style.setProperty(`--${key}`, value)
        })

        theme.value == type
        localStorage.setItem(THEME_KEY, type)
    }

    setTheme()

    return {
        theme,
        setTheme
    }
}

使用

css
.my-bg {
    background-color: var(--primaryColor);
}

.active-text {
    color: var(--activeTextColor)
}
html
<!-- App.vue -->

<template>
    <div class="my-bg">
        <p class="active-text">我是文字</p>
        <p>当前主题色是 {{ theme }}</p>
        <button @click="handleChange">我是按钮</button>
    </div>
</template>
<script setup lang="ts">
import useTheme from '@/hooks/useTheme'
import { ref } from 'vue'
const { theme, setTheme } = useTheme()
const num = ref<number>(0)

const handleChange = () => {
    num.value ++
    setTheme(num.value % 2 === 0 ? 'default' : 'blue')
}
</script>

ok, 主题切换实现

本站中引用到的其他资料,如有侵权,请联系本人删除