🎨如何动态主题切换 —— css变量🖌️

🌀说在前头

大平台比如说b站:

B站 或者百度 这种大平台,确实会广泛使用CSS变量,因为它们能够帮助开发团队在大规模的项目中更好地管理和维护样式 ,特别是在主题切换响应式设计 以及代码优化方面。

CSS变量的优点非常明显:它提高了代码的可维护性可重用性灵活性 ,能够动态修改样式 ,减少冗余,同时也提升了与JavaScript 的交互能力。无论是实现主题切换响应式设计 还是代码优化,CSS变量都能大大简化开发过程。

优点很明显,这也是为啥打开控制台,能看到很多平台都用到了CSS变量

🌀主题切换

定义css变量

首先,我们需要定义两个主题(亮色主题和暗色主题)的CSS变量。我们可以在theme.css文件中这样定义:

定义一个theme.css文件📃:

css 复制代码
/* 默认亮色主题 */
:root {
  --text-color: #333;
  --bg1: hsl(144, 100%, 89%);
  --bg2: hsl(42, 94%, 76%);
}

/* 暗黑主题 */
html[data-theme='dark'] {
  --text-color: #fff;
  --bg1: hsl(198, 44%, 11%);
  --bg2: hsl(198, 39%, 29%);
}

也就是说只要给html加上这么一个自定义属性data-theme='dark',它就是暗黑主题了,就能得到所有暗黑主题下面的所有样式。

html 复制代码
<!DOCTYPE html>
<html>
  <body>
    <div id="app"></div>
  </body>
</html>

使用css变量

Home.vue里面使用这些变量:

js 复制代码
// Home.vue
<template>
  <div class="main">
    <p>{{theme}}</p>
    <ThemeSwitch />
    <h1>Theme Switch</h1>
  </div>
</template>

<script setup lang="ts">
import ThemeSwitch from '../components/ThemeSwitch.vue';
import useTheme from '../utils/useTheme';
const theme = useTheme();
</script>

<style>
.main {
  height: 100vh;
  font-family: serif;
  -webkit-font-smoothing: antialiased;
  background: linear-gradient(to bottom, var(--bg1), var(--bg2));
  color: var(--text-color);
  dispaly: flex;
  justify-content: start;
  align-items: center;
  flex-direction: column;
  font-size: 2em;
  padding-top: 1em;
}
</style>

在这个示例中,我们使用了CSS变量var(--bg1)var(--bg2)var(--text-color),这些变量会根据当前主题的不同而自动切换,确保不同主题下的颜色样式能够正确渲染。

切换主题

为了切换主题,我们需要一个UI组件来处理主题的切换,比如一个开关按钮。这个组件可以像这样简单地实现:

js 复制代码
// ThemeSwitch.vue
<template>
  <div
    class="switch"
    :class="theme"
    @click="theme = theme === 'dark' ? 'light' : 'dark'"
  >
    <div class="bar"></div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
const theme = ref('light');
</script>

<style scoped>
.switch {
  padding: 5px;
  transition: 0.2s ease-in-out;
  width: 120px;
  height: 50px;
  text-align: center;
  background: lightSlateGray;
  box-shadow: -4px 4px 15px inset rgba(0, 0, 0, 0);
  cursor: pointer;
  position: relative;
}
</style>

当用户点击按钮时,我们会切换主题('light' 或 'dark'),并根据选择的主题切换CSS变量的值。

全局共享主题状态

为了使多个组件可以共享和改变主题状态,我们可以将theme变量提取到全局状态管理中。例如,使用一个useTheme.ts文件来管理和共享主题状态:

可以用pinia,这里自己手写一个ref抛出来:

1、设置 document.documentElement.dataset.theme

2、永久性保存

js 复制代码
// useTheme.ts
import { ref } from 'vue';
const them = ref('light');

const LOCAL_KEY = '__theme__';

type Theme = 'light' | 'dark';

const theme = ref<Theme>(localStorage.getItem(LOCAL_KEY) as Theme | 'light');

watchEffect(() => {
  document.documentElement.dataset.theme = theme.value;
  localStorage.setItem(LOCAL_KEY, theme.value); // 为了让主题在页面刷新时保持一致,我们使用了localStorage来保存用户的主题设置:
})

export default function useTheme() {
  return {
    theme
  }
}

ThemeSwitch 改成用共享的数据。

js 复制代码
// ThemeSwitch.vue
<template>
  <div
    class="switch"
    :class="theme"
    @click="theme = theme === 'dark' ? 'light' : 'dark'"
  >
    <div class="bar"></div>
  </div>
</template>

<script setup lang="ts">
import useTheme from '../utils/useTheme';
const { theme } = useTheme(); // 使用useTheme hook解构出当前的主题

以上就是通过CSS变量和Vue的响应式数据实现一个简洁而高效的主题切换功能,效果如下:

🌀总结

就是这里有兼容性问题,需要支持IE或其他不支持CSS变量的浏览器就用动态style去实现,当然除了这种,也可以配合scss、less变量去做。

相关推荐
拉不动的猪32 分钟前
无缝适配 PC 和移动端‌我们要注意哪些点呢
前端·javascript·面试
酱酱们的每日掘金1 小时前
🔥 4 月精选:AICoding Cursor上新与 MCP 实战揭秘!- AI Coding 周刊第 5 期
前端·ai编程·mcp
天天扭码1 小时前
一分钟解决 | 高频面试算法题——和为 K 的子数组(前缀和)
前端·算法·面试
搞瓶可乐2 小时前
鸿蒙ArkUI之布局实战,线性布局(Column,Row)、弹性布局(Flex)、层叠布局(Stack),详细用法
前端·harmonyos·鸿蒙系统·arkui·弹性布局·布局实战·堆叠布局
Aphasia3112 小时前
小厂面试常考算法题整合(一)✍🏻
前端·算法·面试
五月仲夏2 小时前
React基础知识(补充中)
前端·react.js·前端框架
王富贵的记录2 小时前
React 函数组件和类组件的区别
前端·javascript·react.js
yuhaiqiang2 小时前
在公司写代码是工作,在开源社区写代码是生活
前端·后端
左耳咚2 小时前
Egg.js 服务端 HTML 强缓存问题排查与解决
前端·egg.js
DevUI团队3 小时前
Electron 入门学习指南:快速搭建跨平台桌面应用
前端·javascript·electron