likes
comments
collection
share

关于前端主题切换、一键换肤具体实现

作者站长头像
站长
· 阅读数 71

实现思路

目前主流的方案是通过CSS自定义属性(变量)来实现的,将主题有关的颜色,通过业务和语义化的方式命名

ElementUI具体实现

关于前端主题切换、一键换肤具体实现

element-plus官网主题切换是在html标签加了class="dark",使用html.dark,和:root配合改变。 实现源码如下:

关于前端主题切换、一键换肤具体实现

项目中实现主题切换

vue3 + element-plus 项目中实现

  1. 引入
// main.ts  引入暗黑主题css
import 'element-plus/theme-chalk/dark/css-vars.css'
  1. 配置
// index.html配置 -----  class="light"

<!DOCTYPE html>
<html lang="en" class="light">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>主题切换</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
  1. 封装组件
<template>
  <div class="dark-box">
    <el-button text class="switch" :class="isDark ? 'isDark-switch' : 'noDark-switch'" @click="toggleDark">
      <el-icon v-if="isDark">
        <svg viewBox="0 0 24 24">
          <path
            d="M6.05 4.14l-.39-.39a.993.993 0 0 0-1.4 0l-.01.01a.984.984 0 0 0 0 1.4l.39.39c.39.39 1.01.39 1.4 0l.01-.01a.984.984 0 0 0 0-1.4zM3.01 10.5H1.99c-.55 0-.99.44-.99.99v.01c0 .55.44.99.99.99H3c.56.01 1-.43 1-.98v-.01c0-.56-.44-1-.99-1zm9-9.95H12c-.56 0-1 .44-1 .99v.96c0 .55.44.99.99.99H12c.56.01 1-.43 1-.98v-.97c0-.55-.44-.99-.99-.99zm7.74 3.21c-.39-.39-1.02-.39-1.41-.01l-.39.39a.984.984 0 0 0 0 1.4l.01.01c.39.39 1.02.39 1.4 0l.39-.39a.984.984 0 0 0 0-1.4zm-1.81 15.1l.39.39a.996.996 0 1 0 1.41-1.41l-.39-.39a.993.993 0 0 0-1.4 0c-.4.4-.4 1.02-.01 1.41zM20 11.49v.01c0 .55.44.99.99.99H22c.55 0 .99-.44.99-.99v-.01c0-.55-.44-.99-.99-.99h-1.01c-.55 0-.99.44-.99.99zM12 5.5c-3.31 0-6 2.69-6 6s2.69 6 6 6s6-2.69 6-6s-2.69-6-6-6zm-.01 16.95H12c.55 0 .99-.44.99-.99v-.96c0-.55-.44-.99-.99-.99h-.01c-.55 0-.99.44-.99.99v.96c0 .55.44.99.99.99zm-7.74-3.21c.39.39 1.02.39 1.41 0l.39-.39a.993.993 0 0 0 0-1.4l-.01-.01a.996.996 0 0 0-1.41 0l-.39.39c-.38.4-.38 1.02.01 1.41z"
            fill="currentColor"></path>
        </svg>
      </el-icon>
      <el-icon v-else>
        <svg viewBox="0 0 24 24">
          <path
            d="M11.01 3.05C6.51 3.54 3 7.36 3 12a9 9 0 0 0 9 9c4.63 0 8.45-3.5 8.95-8c.09-.79-.78-1.42-1.54-.95A5.403 5.403 0 0 1 11.1 7.5c0-1.06.31-2.06.84-2.89c.45-.67-.04-1.63-.93-1.56z"
            fill="currentColor"></path>
        </svg>
      </el-icon>
    </el-button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const isDark = ref(true)

const toggleDark = () => {
  isDark.value = !isDark.value
  const html = document.querySelector('html')
  if (html) {
    if (isDark.value) {
      html.classList.remove("dark");
      html.classList.add("light");
    } else {
      html.classList.remove("light");
      html.classList.add("dark");
    }
  }
}

</script>

<style scoped lang="scss">
.dark-box {
  margin-right: 20px;
}

// 按钮的基本样式
.switch {
  width: 40px;
  height: 20px;
  border: 1px solid #dcdfe6;
  border-radius: 10px;
  box-sizing: border-box;
  cursor: pointer;
  padding-bottom: 0;
  padding-top: 0px;
  background-color: #ebeef5 !important;
  font-size: 12px;
}

// 暗黑模式样式
.isDark-switch {
  .el-icon {
    background-color: #fff !important;
    padding: 2px;
    border-radius: 50%;
    color: #000;
    margin-left: -8px;
  }
}

// 非暗黑模式样式
.noDark-switch {
  background-color: rgb(8, 8, 8) !important;
  .el-icon {
    color: #fff;
    margin-left: 15px;
  }
}
</style>
  1. 页面引入并使用组件
<template>
  <Dark />
</template>

<script setup lang="ts">
import Dark from './dark.vue'
</script>

总结

上述组件使用了isDark变量来决定显示哪个图标,通过toggleDark事件来切换主题,根据isDark的值添加或移除HTML元素的类名,从而实现了暗黑模式的切换效果。

Nuxt3 项目中实现

  1. 新建主题样式文件
//文件目录: assets/css/theme.scss

/* dark主题 */
:root[theme='dark'] {
    --bg-color: #e2b00e;
    --bg-image: linear-gradient(120deg, #89f7fe 0%, #66a6ff 100%);
    --text-color: #0179f2;
 }
   
    
/* light主题 */
:root[theme='light'], :root {
    --bg-color: #333333;
    --bg-image: linear-gradient(120deg, #0a1314 0%, #161718 100%);
    --text-color: #ffffff;
}
  1. 全局样式使用主题色
// #__nuxt是Nuxt3自动生成的应用窗口ID
html,body,#app,#__nuxt {   
    height: 100%;
    width: 100%;
    margin: 0;    
    padding:0;

    // 主题色
    background-color: var(--bg-color);
    background-image: var(--bg-image);
    color: var(--text-color);
}
  1. 加载页面显示特定主题
// app.vue

onMounted(() => {
    document.documentElement.setAttribute("theme", "dark");
});

  1. 实现主题切换
<template>
    <el-switch v-model="switchValue" @change="add" />
</template>

<script lang="ts" setup>
const switchValue = ref(true);
const add = () => {
    if (!switchValue.value) {
        document.documentElement.setAttribute("theme", "light");
    } else {
        document.documentElement.setAttribute("theme", "dark");
    }
};
</script>
转载自:https://juejin.cn/post/7270503053358907432
评论
请登录