如何实现网页跟随系统主题切换?想必大家都是用过媒体查询@media (prefers-color-scheme: dark)
实现亮/暗主题的切换,那如何让其跟随系统自动切换呢?在window
对象上,有matchMedia
这个API可以帮助我们解决这个问题。它和css中的媒体查询一样的用法,只是这个是在JS中使用。
先看示例:
基本用法:
window.matchMedia('(prefers-color-scheme: dark)')
可以帮我们获取到系统当前的主题色是否为暗色,其返回一个查询结果对象:
写一个简单的示例:
<!DOCTYPE html>
<html lang="en" class="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./main.css">
</head>
<body>
<h1>跟随系统主题切换</h1>
<select class="theme-select" id="select">
<option value="os">跟随系统</option>
<option value="light">浅色主题</option>
<option value="dark">深色主题</option>
</select>
<script>
// 获取系统主题 是否为暗色,当然也可以匹配亮色:prefers-color-scheme: light
const prefers = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)')
// 封装修改html类名
function changeTheme() {
const isDark = prefers.matches
document.documentElement.className = isDark ? 'dark' : 'light'
}
// 获取select标签DOM节点
const dom = document.getElementById('select');
// 页面初始化时 设置select的值
dom.value = prefers.matches ? 'dark' : 'light'
dom.addEventListener('change', function(e) {
const theme = e.target.value
// 当select选择跟随系统时 监听媒体查询对象的change事件,当系统主题改变时 会调用changeTheme
if(theme === 'os') {
changeTheme()
prefers.addEventListener('change', changeTheme)
} else {
// 取消系统主题改变监听
document.documentElement.className = theme;
prefers.removeEventListener('change', changeTheme)
}
})
</script>
</body>
</html>
main.css
:root {
background: #fff;
color: #333;
--select-bg: #f6f6f6;
}
:root.dark {
background: #353434;
color: aliceblue;
--select-bg: #f0f0f0;
}
body {
text-align: center;
padding-top: 50px;
}
.theme-select {
padding: 5px 10px;
background-color: var(--select-bg);
}