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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nginx与keepalived实现集群

提醒一下&#xff1a;下面实例讲解是在mac虚拟机里的Ubuntu系统演示的&#xff1b; Nginx与keepalived实现集群实现的效果 两台服务器都安装Nginx与keepalived&#xff1a; mater服务器的ip(192.168.200.2) backup服务器的ip(192.168.200.4) 将 mater服务器Nginx与keepalived都…

【DG 特长生2019】模拟赛赛后总结(2024.1.24)

打了330pt,订正后350pt T1 签到 T2 dfs剪枝&#xff08;虽然我写挂了&#xff09; T3 NOIP原题 T4 floyd 主要是想分享一下T4。 写了一种基于floyd的做法。 感觉好像和大部分人的写法不太一样。 因为看到大小关系&#xff0c;我就想到了传递性。 floyd是可以维护传递…

Unity中URP下获取每一个额外灯数据

文章目录 前言一、我们先来看一下 SimpleLit 中的调用二、获取额外灯索引1、非移动平台2、非GLES平台3、大多数平台 三、获取额外灯数据 前言 在上一篇文章中&#xff0c;我们知道了URP下是怎么获取额外灯数量的。 Unity中URP下获取额外灯数量 在这篇文章中&#xff0c;我们…

虹科分享丨AR与AI融合加速,医疗护理更便捷!

来源&#xff1a;虹科数字化与AR 虹科分享丨AR与AI融合加速&#xff0c;医疗护理更便捷&#xff01; 原文链接&#xff1a;https://mp.weixin.qq.com/s/Fi0wNfk_TDXRo_1-6cSRNQ 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; #AR眼镜 #医疗护理 根据Reports and Da…

MySQL函数—流程函数

MySQL函数—流程函数&#xff1a;用于实现条件筛选&#xff0c;从而题搞语句的效率。 MySQL函数—流程函数 函数功能IF(value,t,f)如果value为true&#xff0c;则返回t&#xff0c;否则返回fIFNULL(value1,value2)如果value1不为空&#xff0c;返回value1&#xff0c;否则返回v…

5G安卓手机定制_基于天玑900的安卓主板方案

5G安卓手机方案是一款采用联发科MT6877(天玑900)平台的高性能、可运行安卓操作系统的5G智能模块。该手机采用台积电6纳米低功耗工艺&#xff0c;主频高达2.4GHz&#xff0c;内存支持LPDDR5&#xff0c;并支持5G Sub-6GHz全频段和5G双载波聚合技术等多种制式。同时&#xff0c;该…

docker相关

下载Ubuntu18.04文件64位&#xff08;32位安装不了MySQL&#xff09; https://old-releases.ubuntu.com/releases/18.04.4/?_ga2.44113060.1243545826.1617173008-2055924693.1608557140 Linux ubuntu16.04打开控制台&#xff1a;到桌面&#xff0c;可以按快捷键ctrlaltt 查…

国民技术N32G430C8开发笔记一-新建IAR工程

一、创建IAR工程 1、新建工程&#xff0c;保存到project文件夹。 2、添加SDK到工程。 根据原厂SDK的文件结构在IAR新建相应分组&#xff0c;把各个文件夹的文件加载进去&#xff0c;其中startup文件选择IAR平台的startup_n32g430_EWARM.s。 3、添加头文件路径&#xff0…

2024-01-24(ElasticSearch)

1.mysql和elasticsearch的架构&#xff1a; 2.IK分词器利于分中文词汇。 底层是有一个中文字典&#xff0c;这个字典中的中文词汇也是可以拓展的和禁用某些词。 3.mapping常见属性&#xff1a; type&#xff1a;数据类型 index&#xff1a;是否索引 analyzer&#xff1a;分…

重设红帽Linux root密码:简单实用指南

在使用红帽Linux系统时&#xff0c;我们可能会遇到忘记root密码的情况红帽linux系统root密码&#xff0c;这时候该怎么办呢&#xff1f;本文将详细介绍如何重置红帽Linux系统的root密码。 1.进入单用户模式 首先&#xff0c;我们需要进入单用户模式。开机时红帽linux系统root…

一个使用pyqt的word文档查重工具

一个使用pyqt的word文档查重工具 使用场景代码使用截图打包好的软件下载链接结尾 使用场景 有时我们在借鉴一篇文档之后还不想有太多重复&#xff0c;这个时候可以使用这个工具对两个word文档进行对比 代码 import sys from PyQt5.QtWidgets import QApplication, QMainWind…

Redisson 分布式锁解决主从一致性问题的原理

目录 一、主从不一致产生原因 二、Redisson 解决主从一致性的原理 一、主从不一致产生原因 1. Redis 主从集群&#xff1a;主从读写分离&#xff0c;主节点将数据同步给从节点 主节点&#xff1a;增删改从节点&#xff1a;读 2. 主从同步存在延迟&#xff0c;若主节点宕机…

前端开发提高效率的两大工具

一、浏览器中的开发者工具 怎么启动开发者工具&#xff1f; 在浏览器中按下F12或者鼠标右键点击检查 怎么利用&#xff08;常用的几点&#xff09;&#xff1f; 1、元素 点击标红的图标可以用于在页面选择元素&#xff0c;同时右侧会找到元素在前端代码中的位置 点击下方红…

Hudi学习笔记(一)

大数据发展背景 Hudi用于管理分布式文件系统上大型分析数据集存储&#xff0c;支持Spark和Flink整合。它能够是DFS数据集在分钟级时延内支持变更&#xff0c;也支持下游系统对这个数据集的增量处理。 学习目标 什么是数据湖为什么使用数据湖Hudi基本功能如何编译Hudi源码Hud…

vue 解决:Module not found: Error: Can‘t resolve ‘vue-router‘ 的问题

1、问题描述&#xff1a; 其一、报错为&#xff1a; Module not found: Error: Cant resolve vue-router 中文为&#xff1a; 找不到模块&#xff1a;错误&#xff1a;无法解析“vue-router” 其二、问题描述为&#xff1a; 根据报错的中文信息可知&#xff1a;应该是无法…

【linux】远程桌面连接到Debian

远程桌面连接到Debian系统&#xff0c;可以使用以下几种工具&#xff1a; 1. VNC (Virtual Network Computing) VNC&#xff08;Virtual Network Computing&#xff09;是一种流行的远程桌面解决方案&#xff0c;它使用RFB&#xff08;Remote Framebuffer Protocol&#xff0…

spring中循环依赖问题、Servlet 的过滤器与 Spring 拦截器区别

spring中的循环依赖问题 当A类中关联B&#xff0c;B类中关联A class A {B b; } class B {A a; } 正常java代码中new A时&#xff0c;b为null&#xff1b;new B时&#xff0c;a为null&#xff1b; 但是在spring中&#xff0c;由于对象是由spring容器管理的&#xff0c;当创建…

【开源】基于JAVA语言的新能源电池回收系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户档案模块2.2 电池品类模块2.3 回收机构模块2.4 电池订单模块2.5 客服咨询模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 E-R 图设计 四、系统展示五、核心代码5.1 增改电池类型5.2 查询电池品类5.3 查询电池回…

35、WEB攻防——通用漏洞XSS跨站反射存储DOM盲打劫持

文章目录 XSS产生于前端的漏洞&#xff0c;常产生于&#xff1a; XSS分类&#xff1a; 反射型&#xff08;非持久型&#xff09; 存储型&#xff08;持久型&#xff09;&#xff0c;攻击代码被写入数据库中。常见于&#xff1a;写日志、留言、评论的地方 DOM型 DOM型XSS与…

Kubernetes-Taint (污点)和 Toleration(容忍)

目录 一、Taint&#xff08;污点&#xff09; 1.污点的组成 2.污点的设置、查看和去除 3.污点实验&#xff1a; 二、Toleration&#xff08;容忍&#xff09; 1.容忍设置的方案 2.容忍实验&#xff1a; Taint 和 toleration 相互配合&#xff0c;可以用来避免 pod 被分配…