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

目录

🎉应用背景

🎉分析实现思路

🎉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滑块来切换,中间放入小图标,让其看起来效果更佳。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/346764.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

考研C语言刷题基础篇之数组(一)

目录 第一题&#xff1a;用数组作为参数实现冒泡排序 不用函数的冒泡排序 冒泡排序原理&#xff1a; 错误的数值传参冒泡排序 错误的原因 就是什么是数组名 正确的数组传参的冒泡排序 数组的地址和数组首元素的地址的区别 第一题&#xff1a;用数组作为参数实现冒泡排…

unity36——原神等手游常用的物理bone(弹簧)裙摆,与Cloth(布料)裙摆插件 Magica Cloth 使用教程(一)

目前我们手游开发&#xff0c;经常会遇到头发&#xff0c;双马尾&#xff0c;长裙&#xff0c;飘带等。以前我们都是在三维软件中制作骨骼后&#xff0c;自己手动K针。这样做有一些弊端&#xff0c;时间长&#xff0c;并且K帧的飘带效果没法随着游戏中角色的移动&#xff0c;旋…

DSP-TMS320F2837x学习---X-BAR

X-BAR主要包括三部分&#xff1a;输入X-BAR、输出X-BAR、ePWM X-BAR、CLB-XBAR&#xff08;注&#xff1a;28377D及以下不含有CLB模块&#xff09; 一、输入X-BAR 输入X-BAR可以访问每个GPIO&#xff0c;送到不同IP模块&#xff0c;例如ADC、ePWM、外部中断等。 注意&#xf…

深度学习剖根问底: Adam优化算法的由来

在调整模型更新权重和偏差参数的方式时&#xff0c;你是否考虑过哪种优化算法能使模型产生更好且更快的效果&#xff1f;应该用梯度下降&#xff0c;随机梯度下降&#xff0c;还是Adam方法&#xff1f; 这篇文章介绍了不同优化算法之间的主要区别&#xff0c;以及如何选择最佳…

搬运5款超级好用的效率软件

​ 今天再来推荐5个超级好用的效率软件&#xff0c;无论是对你的学习还是办公都能有所帮助&#xff0c;每个都堪称神器中的神器&#xff0c;用完后觉得不好用你找我。 1.绘图软件——Krita ​ Krita是一款专业的开源绘图软件&#xff0c;适用于数字绘画、动画、漫画、插画等领…

qt-C++笔记之使用信号和槽实现跨类成员变量同步响应

qt-C笔记之使用信号和槽实现跨类成员变量同步响应 —— 杭州 2024-01-24 code review! 文章目录 qt-C笔记之使用信号和槽实现跨类成员变量同步响应1.运行2.main.cpp3.test.pro4.编译 1.运行 2.main.cpp 代码 #include <QCoreApplication> #include <QObject> #…

Redisson 分布式锁可重入的原理

目录 1. 使用 Redis 实现分布式锁存在的问题 2. Redisson 的分布式锁解决不可重入问题的原理 1. 使用 Redis 实现分布式锁存在的问题 不可重入&#xff1a;同一个线程无法两次 / 多次获取锁举例 method1 执行需要获取锁method2 执行也需要&#xff08;同一把&#xff09;锁如…

Backtrader 文档学习-Order OCO orders

Backtrader 文档学习-Order OCO orders 主要是可以使用订单组的管理策略&#xff0c;使用订单组策略&#xff0c;则一组订单中&#xff0c;有一个符合条件的订单成交&#xff0c;订单组中其他的订单就自动被取消。 1.概述 V1.9.36.116 版本交互式代理支持StopTrail、StopTra…

初探二分法

推荐阅读 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;一&#xff09; 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;二&#xff09; 文章目录 推荐阅读题目解法一解法二 题目 题目&#xff1a;给定一个 n 个元素有序的&#xff0…

图像旋转角度计算并旋转

#!/usr/bin/python3 # -*- coding: utf-8 -*- import cv2 import numpy as np import timedef Rotate(img, angle0.0,fill0):"""旋转:param img:待旋转图像:param angle: 旋转角度:param fill&#xff1a;填充方式&#xff0c;默认0黑色填充:return: img: 旋转后…

[已解决]504 Gateway Time-out 网关超时

文章目录 问题&#xff1a;504 Gateway Time-out 504 Gateway Time-out 网关超时思路解决 问题&#xff1a;504 Gateway Time-out 504 Gateway Time-out 网关超时 思路 网上的常规思路是修改nginx配置文件,增加请求执行时间,试过没有用 keepalive_timeout 600; fastcgi_con…

凭服务出圈的海底捞,竟然在这件事上也很卷

1月9日&#xff0c;法大大与企业绿色发展研究院联合发布了《2023年签约减碳与低碳办公白皮书》&#xff08;点击阅读及下载&#xff1a;法大大推出“签约减碳”年度账单&#xff0c;引领低碳办公新风潮&#xff09;&#xff0c;该白皮书基于《低碳办公评价》标准倡导的创新减碳…

qt-C++笔记之命令行编译程序,特别是使用Q_OBJECT宏包含了moc(Meta-Object Compiler)的情况

qt-C笔记之命令行编译程序&#xff0c;特别是使用Q_OBJECT宏包含了moc(Meta-Object Compiler)的情况 —— 杭州 2024-01-24 code review! 文章目录 qt-C笔记之命令行编译程序&#xff0c;特别是使用Q_OBJECT宏包含了moc(Meta-Object Compiler)的情况1.问题现象&#xff1a;q…

eNSP学习——交换机配置Trunk接口

目录 原理概述 实验内容 实验目的 实验步骤 实验拓扑 实验编址&#xff1a; 试验步骤 基本配置 创建VLAN&#xff0c;配置Access接口 配置Trunk接口 思考题 原理概述 在以太网中&#xff0c;通过划分VLAN来隔离广播域和增强网络通信的安全性。以太网通常由多台交换机组…

架构师之路(十五)计算机网络(网络层协议)

前置知识&#xff08;了解&#xff09;&#xff1a;计算机基础。 作为架构师&#xff0c;我们所设计的系统很少为单机系统&#xff0c;因此有必要了解计算机和计算机之间是怎么联系的。局域网的集群和混合云的网络有啥区别。系统交互的时候网络会存在什么瓶颈。 ARP协议 地址解…

水雾发生器走过路过不要错过

一、细水雾灭火机理与结构特征如下&#xff1a; 瓦斯输送管道细水雾发生器&#xff0c;是根据细水雾灭火机理及煤矿瓦斯的燃烧特性而进行研制的。其灭火机理&#xff1a; 一是冷却&#xff0c;细水雾颗粒容易气化&#xff0c;大量吸热&#xff0c;迅速降温&#xff0c;终止燃烧…

【JavaWeb】会话管理 cookie session 三大域对象总结

文章目录 会话管理一、Cookie1.1 Cookie的使用1.2 Cookie的时效性1.3 Cookie的提交路径 二、Session2.1 HttpSession的使用2.2 HttpSession时效性 三、三大域对象3.1 域对象概述3.2 域对象的使用 总结 会话管理 HTTP是无状态协议 无状态就是不保存状态,即无状态协议(stateless)…

解决Sublime Text V3.2.2中文乱码问题

目录 中文乱码出现情形通过安装插件来解决乱码问题 中文乱码出现情形 打开一个中文txt文件&#xff0c;显示乱码&#xff0c;在File->Reopen With Encoding里面找不到支持简体中文正常显示的编码选项。 通过安装插件来解决乱码问题 安装Package Control插件 打开Tool->…

【数据结构与算法】栈(Stack)之 浅谈数组和链表实现栈各自的优缺点

文章目录 1.栈介绍2. 哪种结构实现栈会更优&#xff1f;3.栈代码实现&#xff08;C语言&#xff09; 往期相关文章&#xff1a; 线性表之顺序表线性表之链表 1.栈介绍 栈是一种特殊的线性表&#xff0c;只允许在栈顶&#xff08;Top&#xff09;进行插入和删除元素操作&#…

【项目日记(四)】第一层: 线程缓存的具体实现

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:项目日记-高并发内存池⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你做项目   &#x1f51d;&#x1f51d; 开发环境: Visual Studio 2022 项目日…