Appearance
网页实现跟随系统主题变色,附纯CSS解决方案和传统解决方案
页面跟随系统主题切换暗黑模式之前一直是用js实现的,虽然也并不是非常复杂,但是系统的监听总归不是非常优雅。
传统解决方案
js
/**
* 根据用户的系统偏好设置,更新页面的主题样式(暗色/亮色模式)
*/
function updateDarkModeTheme() {
// 检查用户是否启用了暗色模式(操作系统级别的偏好设置)
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
// 使用 classList.toggle 方法切换 'dark-mode' 类:
// 如果 isDarkMode 为 true,则添加该类;
// 否则,移除该类。
document.body.classList.toggle('dark-mode', isDarkMode);
}
// 页面加载时立即应用一次用户的主题偏好
updateDarkModeTheme();
// 创建一个媒体查询对象,用于监听系统颜色方案的变化
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
// 推荐使用现代标准的 addEventListener 方式监听变化(适用于大多数现代浏览器)
if (typeof mediaQuery.addEventListener === 'function') {
mediaQuery.addEventListener('change', updateDarkModeTheme);
} else {
// 对于不支持 addEventListener 的旧浏览器(如 Safari 13 及更早版本)
// 回退使用旧的监听方式:addListener
mediaQuery.addListener(updateDarkModeTheme);
}
一直以来我都是用的这种解决方案,但是这种解决方案也有一些弊端。
- 完全响应系统主题,用户无法通过页面上的按钮或其他方式主动选择亮色/暗色模式。
- 首次加载时可能存在“闪屏”
- 当用户更改系统主题时,网页立即切换样式,没有过渡效果。
最新解决方案
CSS在2024年上了一个新的API —— light-dark()
简单的说这个函数接受两个参数,一个是浅色模式下的色值,一个是暗黑模式下的色值。
css
:root {
--color: light-dark('#333', '#ddd');
--background-color: light-dark('#fff', '#eee');
}
但是需要注意,毕竟是新的API,老旧浏览器肯定是不支持。兼容性请查看下方的表格,新版浏览器一般都没啥问题。