基于css变量轻松实现网站的主题切换功能

我们经常看到一些网站都有主题切换,例如vue官方文档。那他是怎么实现的呢?

在这里插入图片描述

检查元素,发现点击切换时,html元素会动态的添加和移除一个class:dark,然后页面主题色就变了。仔细想想,这要是放在以前,可能要写两套样式,就像这样:

body {background-color: '#fff';
}
body.dark {background-color: '#000';
}

这写起来得多麻烦啊,而且难以维护。

好在我们有CSS变量,早在2017年,微软宣布Edge浏览器将支持CSS变量,现在几乎所有的浏览器都已经支持了这个功能。(IE:啊这?)

css变量也是变量,就像js一样,先声明,再读取。

body {--text-color: red;
}
.box {color: var(--text-color);
}

已经出来很多年了,今天就不详细介绍了,有兴趣的推荐阅读 阮一峰老师的《CSS 变量教程》

今天就用vue3项目来写一个基于css变量实现的主题切换demo。

创建一个vue3项目:

npm create vue@latest

创建一个theme.css文件。

/***默认主题*/
:root {--bg: #fff;--text-color: #000;
}
/***添加属性,用来控制暗黑模式时的样式*/
html[data-theme="dark"] {--bg: #000;--text-color: #fff;
}

或者像vue文档中一样使用class,如下所示:

:root {--bg: #fff;--text-color: #000;
}
html.dark {--bg: #000;--text-color: #fff;
}

但是如果某个页面内无意中野使用到同名dark这个class,可能会造成影响,我这里还是用属性。

main.js中引入一下theme.css

import './assets/theme.css'import { createApp } from 'vue'
import App from './App.vue'createApp(App).mount('#app')

App.vue style中调用一下变量,并动态改变data-theme的值:

<template><main><p>主题切换demo</p><button @click="change">切换</button></main>
</template>
<script>let theme = 'light'const change = () => {theme = theme === 'light' ? 'dark' : 'light'document.documentElement.setAttribute('data-theme', theme)}
</script><style scoped>
main {display: flex;flex-direction: column;align-items: center;justify-content: center;height: 100vh;background-color: var(--bg);color: var(--text-color);
}
p {margin: 20px 0;
}
</style>

看看效果:

在这里插入图片描述

功能基本上已经实现了,再来把这个切换操作封装成一个组件,并全局实时共享主题数据。

创建一个useTheme.js,用来执行设置属性的操作:

import { ref, watchEffect } from 'vue'// 默认用亮色
const theme = ref('light')// 每次改变都设置一下
watchEffect(() => {document.documentElement.setAttribute('data-theme', theme.value)
})export default function useTheme() {return {theme}
}

创建一个switch-theme.vue组件,仅仅用来改变theme的值:

<template><el-switch v-model="theme":active-action-icon="Moon":inactive-action-icon="Sunny"active-color="#2f2f2f"active-value="dark"inactive-value="light"@change="changeDark"></el-switch>
</template><script setup>import { Sunny, Moon } from '@element-plus/icons-vue'import useTheme from '../hooks/useTheme'const { theme } = useTheme()const changeDark = (data) => {theme.value === data}
</script>

改一下App.vue文件,引入并使用ThemeSwitch组件和useTheme Hook:

<template><main><p>主题切换demo</p><ThemeSwitch></ThemeSwitch><p>当前主题:{{theme}}</p></main>
</template><script setup>import ThemeSwitch from './components/theme-switch.vue'import useTheme from './hooks/useTheme'const { theme } = useTheme()
</script><style scoped>
main {display: flex;flex-direction: column;align-items: center;justify-content: center;height: 100vh;background-color: var(--bg);color: var(--text-color);
}
p {margin: 20px 0;
}
</style>

再看看效果:

在这里插入图片描述

现在由一个专门的组件用来控制切换主题,并且不同组件内也都能共享theme变量了。

最后再优化一下,目前默认是亮色,切换到暗色以后再刷新页面,又会回到亮色,可以把theme变量存到localstorage

修改一下useTheme.js:

import { ref, watchEffect } from 'vue'// 从取缓存中取值,给个默认值。
const theme = ref(localStorage.getItem('theme') || 'light')// 每次改变都设置一下属性,并存到缓存中。
watchEffect(() => {document.documentElement.setAttribute('data-theme', theme.value)localStorage.setItem('theme', theme.value)
})export default function useTheme() {return {theme}
}

全部代码见Github

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

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

相关文章

电缆隧道在线监测系统:提升电力设施安全与效率的关键

随着城市化进程的加快&#xff0c;电力电缆隧道在保障城市电力供应方面的地位日益重要。然而&#xff0c;电缆隧道环境复杂&#xff0c;容易受到多种因素影响&#xff0c;如温度、湿度、烟雾、水位等&#xff0c;严重威胁电力设施的安全与稳定运行。在此背景下&#xff0c;电缆…

修改switch Nand无线区码 以支持高频5G 信道

环境&#xff1a;NS switch 问题&#xff1a;日版&#xff0c;港版无法连接大于44信道的5G WIFI 解决办法&#xff1a;修改PRODINFO.dec的WIFI 区域码 背景&#xff1a;我的switch是最早买的港版的一批&#xff0c;WIFI 只能连接日本的信道&#xff0c;家里的路由器是国行的&am…

国庆day1---消息队列实现进程之间通信方式代码,现象

snd&#xff1a; #include <myhead.h>#define ERR_MSG(msg) do{\fprintf(stderr,"__%d__:",__LINE__);\perror(msg);\ }while(0)typedef struct{ long msgtype; //消息类型char data[1024]; //消息正文 }Msg;#define SIZE sizeof(Msg)-sizeof(long)int main…

释放潜力:人工智能对个性化学习的影响

人工智能有潜力通过使个性化学习成为一种实用且可扩展的方法来彻底改变教育。它使教育工作者能够满足每个学生的独特需求&#xff0c;促进参与并提高整体学习成果。然而&#xff0c;必须解决道德问题&#xff0c;并确保技术仍然是教育工作者手中的工具&#xff0c;为学生创造更…

Mysql——三、SQL语句(上篇)

Mysql 一、SQL语句基础1、SQL简介2、SQL语句分类3、SQL语句的书写规范 二、数据库操作三、MySQL 字符集1、变量2、utf8和utf8mb4的区别 四、数据库对象五、SELECT语句1、简单的SELECT语句2、SQL函数2.1 聚合函数2.2 数值型函数2.3 字符串函数2.4 日期和时间函数2.5 流程控制函数…

云原生开发:从容器到微服务的全栈指南

文章目录 什么是云原生开发&#xff1f;1. 容器化2. 微服务架构 云原生开发的优势1. 可伸缩性2. 高可用性3. 灵活性4. 快速交付 云原生开发的1. 学习曲线2. 复杂性3. 运维挑战 云原生开发的最佳实践1. 自动化部署2. 监控和日志3. 安全性4. 弹性设计5. 文档和培训 未来展望结论 …

C++ 迭代器(iterator)

迭代器介绍 迭代器&#xff08;iterator&#xff09;&#xff1a;容器类型内置的“指针” - 使用迭代器可以访问某个元素&#xff0c;迭代器也能从一个元素移动到另一个元素。 - 有迭代器的类型都拥有 begin 和 end 成员- begin&#xff1a;返回指向第一个元素&#xff08;或字…

博客无限滚动加载(html、css、js)实现

介绍 这是一个简单实现了类似博客瀑布流加载功能的页面&#xff0c;使用html、css、js实现。简单易懂&#xff0c;值得学习借鉴。&#x1f44d; 演示地址&#xff1a;https://i_dog.gitee.io/easy-web-projects/infinite_scroll_blog/index.html 代码 index.html <!DOCT…

知识工程---neo4j 5.12.0+GDS2.4.6安装

&#xff08;已安装好neo4j community 5.12.0&#xff09; 一. GDS下载 jar包下载地址&#xff1a;https://neo4j.com/graph-data-science-software/ 下载得到一个zip压缩包&#xff0c;解压后得到jar包。 二. GDS安装及配置 将解压得到的jar包放入neo4j安装目录下的plugi…

【数据结构--八大排序】之冒泡排序+选择排序+插入排序

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

ROS系统读取USB相机图像数据

ROS系统读取USB相机图像数据 前言usb_cam 功能包下载与编译摄像头选择连接摄像头可配置参数 前言 usb_cam功能包简介 为了丰富机器人与外界的交互方式&#xff0c;已经增加了与机器人的语音交互方式&#xff0c;不仅使机器人能够说话发声&#xff0c;还能听懂我们说的话&#…

26947-2011 手动托盘搬运车 学习记录

声明 本文是学习GB-T 26947-2011 手动托盘搬运车. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了手动托盘搬运车(以下简称托盘车)的结构参数、技术要求、试验方法、检验规则、 标志、包装、运输和贮存。 本标准适用于额定载荷…

GPIO的输入模式

1. GPIO支持4种输入模式&#xff08;浮空输入、上拉输入、下拉输入、模拟输入&#xff09; 1. 模拟输入 首先GPIO输出部分(N-MOS,P-MOS)是不起作用的。并且TTL施密特触发器也是不工作的。 上下拉电阻的开关都是关闭的。相当于I/o直接接在模拟输入。 模拟输入模式下&#xff…

【每日一题】种花问题

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;贪心 写在最后 Tag 【贪心】【数组】【2023-09-29】 题目来源 605. 种花问题 题目解读 种花要种在空地&#xff08;没有种过花的位置&#xff09;上&#xff0c;花不能种在相邻位置上否则会抢夺水资源无法正常生长&a…

ChatGPT,AIGC 助力人力资源管理对身份证号处理

HR&#xff0c;行政&#xff0c;文员办公对于员工信息管理中有一项目非常重要的操作&#xff0c;便是从身份证号中提取相关信息如下&#xff1a; 可以用ChatGPT完成三个字段的提取与计算。 我们先让ChatGPT描述一下身份证号每一位都代表什么意思。 接下来从身份证号中提取出生…

集合-ArrayList源码分析(面试)

系列文章目录 1.集合-Collection-CSDN博客​​​​​​ 2.集合-List集合-CSDN博客 3.集合-ArrayList源码分析(面试)_喜欢吃animal milk的博客-CSDN博客 目录 系列文章目录 前言 一 . 什么是ArrayList? 二 . ArrayList集合底层原理 总结 前言 大家好,今天给大家讲一下Arra…

高仿互站网多套模板完整源码

高仿互站网 后台手机端两套模板 电脑端二十套模版&#xff0c;简单介绍几个功能&#xff0c; 支持用户注册开店 开店申请&#xff0c;支持用户发布自己商品 支持卡密形式或实物形式&#xff0c; 支持用户自己发布求助 任务大厅功能&#xff0c;源码完整 更多功能自己去发现吧…

iTOP-RK3588开发板体验RKNN_DEMO

RKNN 是 Rockchip NPU 平台(也就是开发板)使用的模型类型&#xff0c;是以.rknn 结尾的模型文件。 RKNN SDK 提 供 的 demo 程 序 中 默 认 自 带 了 RKNN 模 型 &#xff0c; 在 RKNN SDK 的 examples/rknn_yolov5_demo/model/RK3588/目录下&#xff0c;如下图所示&#xff…

爬取北京新发地当天货物信息并展示十五天价格变化(三)---获取物品十五天内的价格

。。。。。。。。。。。。。。。。。。。。。。 1.网页请求一下内容2.通过爬虫进行请求3.获取商品十五天详细数据并绘制折线图4.项目详细代码 1.网页请求一下内容 通过抓包我们发现一共七个参数 limit: 20 # 一页多少数据 current: …

Python计算巴氏距离

Python计算巴氏距离 巴氏距离简介 在统计中&#xff0c;巴氏距离&#xff08;Bhattacharyya Distance&#xff09;测量两个离散或连续概率分布的相似性。它与衡量两个统计样品或种群之间的重叠量的巴氏系数密切相关。巴氏距离和巴氏系数以20世纪30年代曾在印度统计研究所工作…