首页 前端知识 使用CSS 或 SASS 实现主题背景切换效果

使用CSS 或 SASS 实现主题背景切换效果

2024-03-07 08:03:14 前端知识 前端哥 881 10 我要收藏

目录

🎉应用背景

🎉分析实现思路

🎉CSS实现主题切换

🎉SCSS实现主题切换

 🎉结语


🎉应用背景

现在的主流网站中,无论是一些技术文档获取官网,都存在着使用一个switch按钮实现主题背景切换的一个效果,那么这种效果是怎么实现的呢?

🎉分析实现思路

其实我们去查看一些携带了这种功能的官网,可以看到他们是在html标签这种通过控制其类名来实现的主题切换,我们可以参考这种思路来定义我们自己的主题。

 

🎉CSS实现主题切换

css来实现主题切换,需要用到的是css变量,我们可以根据项目主题定义二套变量,然后通过判断html元素上面的class变量来实现切换主题。

我在style.css文件中定义了二套主题,root下的是默认的主题,dark下的是暗色主题 

:root {
  --main-bgc: pink;
  --main-text-color: black;
}

.dark {
  --main-bgc: #000;
  --main-text-color: #fff;
}

 

<template>
  <div class="item">
    <h1>当前主题为亮色</h1>
    <button class="btn1" @click="changeTheme">点击切换主题</button>
  </div>
</template>

<style>
.item {
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;

  background-color: var(--main-bgc);
  color: var(--main-text-color);
}
</style>

当前的效果是这样的,记得一定要引入style.css,可以看到样式已经生效了 

通过前面的分析我们还定制了一套主题为dark,我们只需要在html标签上面加上类名即可生效

可以看到当前的效果已经实现了,为什么能实现这样的效果,我们通过观察css变量,可以发现他们定义的变量名都是一样的,那么我们得分析为啥添加类名之后就得听dark类名的呢?

当二个样式重复的时候,浏览器听谁的,得看谁的权重高

:root 

.dark

可以发现他们俩的权重是一样高的,但是因为.dark在下面,下面的会覆盖上面的样式,所以现在效果是可以实现的,如果我们将他们俩调换一下位置,效果就无法实现了。

所以这里需要特别的注意位置前后

那么有没有一种方法可以避免这种情况的发生,答案是肯定有的,我们可以实现一个特殊的选择器提高权重

html[data-theme="dark"] {
  --main-bgc: #000;
  --main-text-color: #fff;
}

这个选择器不是类名选择器 是属性选择器,在html上查找此自定义属性,其使用方法与class类名是一样的,添加自定义属性即可。

像这样也是可以实现效果的

要实现手动切换的方式有很多种,可以是一个按钮,可以是一个switch滑块,通过他们的点击或者什么事件来实现切换即可,但是注意刷新后会回到最初的效果,为了刷新后效果不丢失,我们可以将其当前的属性值存储在本地localStorage等中。 下面的scss实现我会写一个小demo,可以参考。

🎉SCSS实现主题切换

首先在项目中我们得安装sass

pnpm i sass

注意scss是不能在main.js文件中直接引入的,需要在组件的样式中引入或者在配置文件中全局注册,像这样在配置文件中配置一下就可以全局使用scss变量了。

 

 

style.scss

// 定义的两套主题
$themes: (
  "light": (
    bgColor: #fff,
    textColor: #000,
    btnColor: pink
  ),
  "dark": (
    bgColor: #000,
    textColor: #fff,
    btnColor: blue
  )
);

// 定义默认主题
$curTheme: "light";

// 定义混合 useTheme()
@mixin useTheme() {
  // 循环生成样式
  @each $key, $value in $themes {
    $curTheme: $key !global;
    .#{$key} & {
      @content; // 将 @content 代表的样式插入到生成的选择器中
    }
  }
}

// 定义函数 getValue($key) 获取当前主题的值
@function getValue($key) {
  $themeMap: map-get($themes, $curTheme);
  @return map-get($themeMap, $key);
}

$themes: 这个变量保存了两套主题(light 和 dark)。每个主题都被定义为一个映射,包含诸如 bgColor、textColor 和 btnColor 等属性。

@mixin useTheme(): 这个混合用于循环遍历 $themes 中的每个主题,这里循环遍历后,我们后期维护起来就会非常的方便,如果要增加主题,就只要在$themes中添加一个即可。对于每个主题,将 $curTheme 设置为全局变量,并使用它生成一个 CSS 选择器(.light 或 .dark)。@content 中的样式将插入到每个生成的选择器中。

@function getValue($key): 这个函数接受一个属性键作为参数,并返回当前主题中该属性的对应值。

那么我们在组件中可以这样使用,@include来应用即可

<template>
  <div class="item">
    <h1>当前主题为暗色</h1>
    <button class="btn1" @click="changeTheme">点击切换主题</button>
    <button class="btn2">测试按钮主题是否切换</button>
  </div>
</template>

<style lang="scss" scoped>
.item {
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;

  @include useTheme {
    background-color: getValue('bgColor');
    color: getValue('textColor');
  }
}
.btn1 {
  padding: 10px;
  border: none;
  border-radius: 10px;

  @include useTheme {
    background-color: getValue('btnColor');
  }
}

.btn2 {
  padding: 10px;
  border: none;
  border-radius: 10px;

  @include useTheme {
    background-color: getValue('btnColor');
  }
}
</style>

现在我们只要通过添加class类名即可实现主题切换的效果

 其实通过观察上面的代码,按钮部分是有很多重复的代码的,难道每次新加一个元素就得调用一次@include嘛? 这时候为了减少重复代码,我们可以使用@mixin混入实现这样的效果。

 

@mixin buttonStyles {
  padding: 10px;
  border: none;
  border-radius: 10px;
  margin: 10px;
  @include useTheme {
    background-color: getValue("btnColor");
  }
}

在组件中给需要实现主题切换的按钮调用该混入即可

.btn1 {
  @include buttonStyles;
}

.btn2 {
  @include buttonStyles;
}

实现按钮点击主题切换,其实完成这个效果,上面也已经提供了思路,直接写大家肯定是能写出来的,但是为了效率呢,咱们可以使用一下封装好的库帮我们完成这个效果,(实则是为了偷懒,😄)。

我们可以使用@vueuse/core来帮我们实现切换类名的效果

安装@vueuse/core

npm i @vueuse/core

加上这样一段配置,给按钮绑定好触发事件,启动服务

 <div class="item">
    <h1>当前主题为{{ isDark ? '暗色' : '亮色' }}</h1>
    <button @click="toggle()" class="btn1">点击切换主题</button>
  </div>

import { useDark, useToggle } from '@vueuse/core'
const isDark = useDark({
  // 存储到localStorage/sessionStorage中的Key 根据自己的需求更改
  storageKey: 'useDarkKEY',
  // 暗黑class名字
  valueDark: 'dark',
  // 高亮class名字
  valueLight: 'light',
})

const toggle = useToggle(isDark);

启动服务后可以在localStorge中看到这样一个数据

这就是我们之前配置的颜色,@vueuse/core的实现思路也是将当前的主题存储到本地,实现刷新不丢失的效果。

 这样之后,我们的点击切换主题效果就完成了。

 

 🎉结语

二种实现主题切换的功能都完成了,可以继续扩展功能,可以做一个switch滑块来切换,中间放入小图标,让其看起来效果更佳。

转载请注明出处或者链接地址:https://www.qianduange.cn//article/3366.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!