实现Tailwind Darkmode:支持系统偏好与手动切换
暗黑模式适配系统偏好+手动切换解决方案
原代码存在两个核心问题:初始化时未给系统暗色偏好的场景添加dark类,且未监听系统配色偏好的变化事件,导致无法自动跟随系统主题切换。以下是修复后的完整实现:
修复后的JS代码
// 暗黑/亮色模式切换 const themeToggleDarkIcon = document.getElementById('moon'); const themeToggleLightIcon = document.getElementById('sun'); const themeToggleBtn = document.getElementById('theme-toggle'); const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); // 统一更新主题状态的函数 function updateTheme(isDark) { if (isDark) { document.documentElement.classList.add('dark'); themeToggleLightIcon.classList.remove('hidden'); themeToggleDarkIcon.classList.add('hidden'); } else { document.documentElement.classList.remove('dark'); themeToggleDarkIcon.classList.remove('hidden'); themeToggleLightIcon.classList.add('hidden'); } } // 初始化主题 const savedTheme = localStorage.getItem('color-theme'); if (savedTheme) { // 优先使用本地存储的主题设置 updateTheme(savedTheme === 'dark'); } else { // 无本地存储时,跟随系统偏好 updateTheme(darkModeMediaQuery.matches); } // 手动切换主题按钮事件 themeToggleBtn.addEventListener('click', function() { const currentIsDark = document.documentElement.classList.contains('dark'); const newTheme = currentIsDark ? 'light' : 'dark'; updateTheme(!currentIsDark); localStorage.setItem('color-theme', newTheme); }); // 监听系统配色偏好变化 darkModeMediaQuery.addEventListener('change', function(e) { // 仅当用户未手动设置过主题时,跟随系统变化 if (!localStorage.getItem('color-theme')) { updateTheme(e.matches); } });
配套按钮代码
<button id="theme-toggle" type="button" class="p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors"> <svg id="moon" class="hidden h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path> </svg> <svg id="sun" class="hidden h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path> </svg> </button>
关键修改说明
- 抽离
updateTheme函数,统一处理主题类切换和图标显示逻辑,避免代码冗余 - 初始化阶段修复:无本地存储时,根据系统偏好正确设置
dark类和对应图标 - 添加
prefers-color-scheme媒体查询监听,用户未手动设置主题时,自动跟随系统主题变化 - 简化手动切换逻辑,直接通过当前主题状态判断新主题,代码更简洁
内容的提问来源于stack exchange,提问作者user18336975
相关产品推荐
相关产品推荐

