网页主题自动适配:网页跟随系统自动切换主题

主题切换是网站设计中一个非常有趣的功能,它允许用户在多种预先设计的样式之间轻松切换,以改变网站的视觉表现。最常见的就是白天和黑夜主题的切换,用户可以根据自己的喜好进行设置。
除了让用户手动去切换主题外,如果能够让用户第一次访问时,网站就设置为用户系统的主题样式,这无疑是一种更好的体验。

主题切换

CSS主题切换有多种方式实现,这里就简单描述下,不是本文重点

方式1:通过自定义标签属性来实现主题切换

/* 默认主题样式 */
body {
  background-color: white;
  color: black;
}/* 深色主题样式 */
body[data-theme="dark"] {
  background-color: black;
  color: white;
}
:root {
  --body-background: rgb(248, 244, 212);
  --text-color: #000;
}
html[data-theme="dark"] {
  --body-background: rgb(58, 70, 90);
  --text-color: #eee;
}

方式2:运行时动态地修改CSS变量的值,从而实现主题切换的效果

:root {
  --primary-color: #007bff;
  --secondary-color: #6c757d;
  --background-color: white;
  --text-color: black;
}
​
body {
  background-color: var(--background-color);
  color: var(--text-color);
}
document.documentElement.style.setProperty('--background-color', 'black');
document.documentElement.style.setProperty('--text-color', 'white');

方式3:使用类名切换,通过对顶层节点设置不同的类名,然后定义不同类名的CSS样式,切换主题时修改类名即可

.theme-light {
  background-color: white;
  color: black;
}
​
.theme-dark {
  background-color: black;
  color: white;
}
function switchTheme() {
  const bodyElement = document.body;
  if (bodyElement.classList.contains('theme-light')) {
    bodyElement.classList.remove('theme-light');
    bodyElement.classList.add('theme-dark');
  } else {
    bodyElement.classList.remove('theme-dark');
    bodyElement.classList.add('theme-light');
  }
}


方式4:link标签动态引入

function switchTheme(theme) {
  const linkElement = document.createElement('link');
  linkElement.rel = 'stylesheet';if (theme === 'light') {
    linkElement.href = 'theme-light.css'; // 切换为浅色主题
  } else {
    linkElement.href = 'theme-dark.css'; // 切换为深色主题
  }
​
  document.head.appendChild(linkElement);
}

扫码加入前端交流群,期待你的加入!
描述文字

CSS媒体查询

CSS媒体查询是实现响应式网页设计的重要工具,它允许根据设备的特定特性来应用不同的样式规则。

使用 @media 规则可以实现这一功能,通过这个规则可以定义一个或多个条件,当这些条件满足时,相应的样式代码块将会被应用到文档上。例如,在屏幕宽度小于或等于768像素时,背景颜色可以设置为浅蓝色

/* 基础样式 */
body {
  background-color: lightblue;
  color: white;
  font-size: 16px;
  padding: 20px;
}/* 当屏幕宽度小于或等于768像素时,应用以下样式 */
@media (max-width: 768px) {
  body {
    background-color: red;
    color: black;
    font-size: 14px;
    padding: 10px;
  }
}

CSS媒体查询还可以检测用户是否有将系统的主题色设置为两色或者暗色

  • light:表示用户已告知系统选择使用浅色主题界面
  • dark:表示用户已告知系统选择使用暗色主题界面
.day {
  background: #eee;
  color: black;
}
.night {
  background: #333;
  color: white;
}@media (prefers-color-scheme: dark) {
  .day.dark-scheme {
    background: #333;
    color: white;
  }
  .night.dark-scheme {
    background: black;
    color: #ddd;
  }
}@media (prefers-color-scheme: light) {
  .day.light-scheme {
    background: white;
    color: #555;
  }
  .night.light-scheme {
    background: #eee;
    color: black;
  }
}

这种方式的确可以实现主题跟随系统的变换而变换,但是存在以下缺点:

  • 增加工作量:开发者需要编写更多的CSS代码,这可能会导致工作效率降低

  • 加载时间延长:随着CSS代码量的增加,页面的加载时间可能会变长,尤其是对于那些包含大量媒体查询的复杂样式表

  • 用户无法自定义:样式固定,用户无法自定义设置主题样式

JS媒体查询

JS同样拥有媒体查询的方法 matchMedia()。传入一个被用于媒体查询解析的字符串,返回一个用来媒体查询新的 MediaQueryList 对象,其中的 matchs 属性值就是匹配结果。

// 如果视口的宽度小于或等于600像素,则输出为true
const mql = window.matchMedia('(max-width: 600px)');
console.log(mql.matchs)

同样的也可以用来查询系统是否使用了暗色主题

const osThemeIsDark = matchMedia("(prefers-color-scheme: dark)").matches;

接下来就采用上面方式1的主题切换方案,结合JS媒体查询来实现跟随系统主题切换的功能。

:root {
  --body-background: rgb(248, 244, 212);
  --text-color: #000;
}
html[data-theme="dark"] {
  --body-background: rgb(58, 70, 90);
  --text-color: #eee;
}
body {
  padding-top: 200px;
  height: 100vh;
  width: 100vw;
  margin: 0;
  background: var(--body-background);
  text-align: center;
  color: var(--text-color);
}
<body>
  <div>
  <select>
    <option value="light">白天模式</option>
    <option value="dark">黑夜模式</option>
    <option value="os">跟随系统</option>
  </select>
  </div>
  <h1>公众号:前端筱园</h1>
  <p>www.dengzhanyong.com</p>
</body>
const select = document.querySelector('select');
const html = document.querySelector("html");
// 获取用户设置的主题,默认是跟随系统
const localTheme = localStorage.getItem('theme') || 'os';
settingTheme(localTheme);
// 设置select选中的值
select.value = localTheme;
​
select.onchange = (e) => {
const theme = e.target.value;
    settingTheme(theme);
    localStorage.setItem('theme', theme)
}function settingTheme(theme) {
    // 如果是跟随系统,就获取系统的主题
if (theme === 'os') {
const osThemeIsDark = matchMedia("(prefers-color-scheme: dark)").matches;
        html.dataset.theme = osThemeIsDark ? 'dark' : 'light';
    } else {
        html.dataset.theme = theme;
    }
}

监听媒体变化

现在还有一个问题,如果页面已经打开的情况下,再去修改系统主题,是否能检测到系统主题的变化,使得网页在不刷新的情况下自动切换。

答案是可以的,可以通过监听 MediaQueryListchange 事件,当 matches 的值发生变化时会触发。

matchMedia("(prefers-color-scheme: dark)").addEventListener("change", event => {
    html.dataset.theme = event.matches ? 'dark' : 'light';
})

利用媒体查询还可以检测很多内容,比如:浏览器可视区域尺寸、设备尺寸、设备目前处于横向还是纵向、检测设备宽高比、设备颜色位数等

写在最后

欢迎访问我的个人网站:www.dengzhanyong.com

前端筱园交流群】已经正式开通啦!在这里,你可以与一群志同道合的小伙伴们交流、分享、学习、共同成长,扫码加入,期待你的加入!
描述文字
关注我的公众号【前端筱园】,不错过每一篇推送

描述文字

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

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

相关文章

Vue从入门到实战Day03

一、生命周期 1. 生命周期四个阶段 思考&#xff1a; ①什么时候可以发送初始化渲染请求&#xff1f; 答&#xff1a;越早越好&#xff0c;在创建阶段后 ②什么时候可以开始操作DOM&#xff1f; 答&#xff1a;至少DOM得渲染出来&#xff0c;在挂载阶段结束后。 Vue生命周…

Python从0到POC编写--实用小脚本02

爆破脚本&#xff1a; 爆破脚本也是我们经常使用的东西 这里就简单讲讲后台爆破脚本的编写吧 在编写之前&#xff0c;我们先通过访问网站去看看情况 首先我们可以先登录看看 输入账号 admin &#xff0c;密码 12345 后 登录失败&#xff0c;提示 用户名或密码错误 在输入…

MultiBooth:文本驱动的多概念图像生成技术

在人工智能的领域&#xff0c;将文本描述转换为图像的技术正变得越来越先进。最近&#xff0c;一个由清华大学和Meta Reality Labs的研究人员组成的团队&#xff0c;提出了一种名为MultiBooth的新方法&#xff0c;它能够根据用户的文本提示&#xff0c;生成包含多个定制概念的图…

去除视频背景音乐或人物声音的4种方法,建议收藏

你是否曾想移除视频中令人分心的声音呢&#xff1f;对于需要裁剪声音或去除背景噪音的视频来说&#xff0c;消音是一种非常有用的技能。那么&#xff0c;视频怎么消除声音&#xff1f;看看下文就知道了。 方法一&#xff1a;使用 智优影 去除视频中的音频 在线转换工具不仅支持…

怎样选择IT外包公司?需要注意什么?

随着网络化、数字化、智能化快速发展&#xff0c;一部分企业成立自己的IT部门&#xff0c;负责各个科室的网络安全&#xff0c;大部分企业把网络安全、数据安全&#xff0c;外包给专业的IT外包公司&#xff0c;既提升了办公效率&#xff0c;企业又能把主要精力放在发展核心业务…

【C】语⾔内存函数--超详解

1. memcpy 使⽤和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 这个函数在遇到 \0 的时候并不会停下来。 如果source和destination有任何的重叠&am…

Chrono下载管理器:提升下载体验,有效管理文件

名人说&#xff1a;莫愁千里路&#xff0c;自有到来风。 ——钱珝 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、介绍二、下载安装1、Chrome应用商店&#xff08;需科学&#xff09;2、第三方直链下载 三、使…

nacos下载安装和nacos启动报错

nacos简介: Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称&#xff0c;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮助您…

Spring底层入门(九)

boot的执行流程分为构造SpringApplication对象、调用run方法两部分 1、Spring Boot 执行流程-构造 通常我们会在SpringBoot的主启动类中写以下的代码&#xff1a; 参数一是当前类的字节码&#xff0c;参数二是main的args参数。 public class StartApplication {public static…

(一)Linux的vim编辑器的使用

一.vim编辑器 Vim 是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。简单的来说, vi 是老式的字处理器,不过功能已经很齐全了,但是还是有可以进步的地方。 vim 则可以说是程序开发者的一项很好用的工具。 二…

关于勒索攻击,绝大多数企业存在的三个认知误区

网络空间&#xff0c;有一个挥之不去的“幽灵”&#xff0c;它的名字就叫勒索攻击。 近年来&#xff0c;企业遭受勒索攻击的事件被频频曝光。就在不久前&#xff0c;国家安全部曝光了一起境外黑客组织对我国某高新科技企业实施勒索攻击的案例&#xff0c;该企业的相关信息化系统…

Window7镜像注入USB驱动,解决系统安装后无法识别USB

Window7镜像注入usb驱动 Window7镜像注入usb驱动方法一方法二 Window7镜像注入usb驱动 一般4代酷睿之后的主机需要安装usb驱动才能驱动usb&#xff0c;导致很多Windows原版镜像安装后无法识别usb键盘 方法一 1.直接采购PS2 接口键盘、PS2 接口鼠标 方法二 使用联想镜像注入…

光峰科技2023年营收、净利润均双位数下滑,新一年延续?

近日&#xff0c;深圳光峰科技股份有限公司&#xff08;688007.SH&#xff0c;下称“光峰科技”&#xff09;对外公布了2023年和2024年一季度的经营“成绩单”。 透视财报不难看出&#xff0c;虽然光峰科技在降低成本、提振销售等层面下足了功夫&#xff0c;但受制于市场需求式…

测试项目实战——安享理财1(测试用例)

说明&#xff1a; 1.访问地址&#xff1a; 本项目实战使用的是传智播客的安享理财项目&#xff08;找了半天这个项目能免费用且能够满足测试实战需求&#xff09; 前台&#xff1a;http://121.43.169.97:8081/ 后台&#xff1a;http://121.43.169.97:8082/ &#xff08;点赞收藏…

Git泄露(CTFHUB的git泄露)

log 当dirsearch 扫描一下&#xff0c;命令&#xff1a; python dirsearch.py -u url/.git 发现存在了git泄露 借助kali里面&#xff0c;打开GitHack所在的目录&#xff0c;然后 输入&#xff1a; python2 GitHack.py -u url/.git/ 必须要用Python2 tree 命令 可以看到…

Paddle 基于ANN(全连接神经网络)的GAN(生成对抗网络)实现

什么是GAN GAN是生成对抗网络&#xff0c;将会根据一个随机向量&#xff0c;实现数据的生成&#xff08;如生成手写数字、生成文本等&#xff09;。 GAN的训练过程中&#xff0c;需要有一个生成器G和一个鉴别器D. 生成器用于生成数据&#xff0c;鉴定器用于鉴定数据的准确性&…

车载测试___面试题和答案归纳

车载面试题 一、实车还在设计开发阶段&#xff0c;大部分测试通过什么测试&#xff1f; 答案&#xff1a;通过台架和仿真来完成的 二、测试部分划分&#xff1f; 测试部门是分为自研&#xff0c;系统&#xff0c;验收&#xff0c;自研部门是开发阶段测试&#xff0c;系统部门…

95、动态规划-编辑距离

递归暴力解法 递归方法的基本思想是考虑最后一个字符的操作&#xff0c;然后根据这些操作递归处理子问题。 递归函数定义&#xff1a;定义一个递归函数 minDistance(i, j)&#xff0c;表示将 word1 的前 i 个字符转换成 word2 的前 j 个字符所需的最小操作数。 递归终止条件…

llama.cpp制作GGUF文件及使用

llama.cpp的介绍 llama.cpp是一个开源项目&#xff0c;由Georgi Gerganov开发&#xff0c;旨在提供一个高性能的推理工具&#xff0c;专为在各种硬件平台上运行大型语言模型&#xff08;LLMs&#xff09;而设计。这个项目的重点在于优化推理过程中的性能问题&#xff0c;特别是…

(七)JSP教程——session对象

浏览器和Web服务器之间的交互通过HTTP协议来完成&#xff0c;HTTP协议是一种无状态的协议&#xff0c;服务器端无法保留浏览器每次与服务器的连接信息&#xff0c;无法判断每次连接的是否为同一客户端。为了让服务器端记住客户端的连接信息&#xff0c;可以使用session对象来记…