基于Bootstrap 5实现页面加载及主题切换时单选按钮自动选中
解决Bootstrap 5主题切换时单选按钮同步选中状态的问题
问题背景
使用Bootstrap 5官方提供的暗色模式切换JavaScript代码时,页面加载或切换主题时,对应的单选按钮无法自动同步checked状态——默认只有Light按钮被标记为checked,即使本地存储了其他主题也不会自动切换选中项。
修改方案
需要修改showActiveTheme函数,在处理样式类的同时,同步设置单选按钮的checked属性:
const showActiveTheme = (theme, focus = false) => { const themeSwitcher = document.querySelector('#bd-theme') if (!themeSwitcher) { return } // 获取对应主题的单选按钮 const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`) // 重置所有单选按钮的选中状态和样式类 document.querySelectorAll('[data-bs-theme-value]').forEach(element => { element.classList.remove('checked') element.checked = false }) // 设置目标按钮的选中状态和样式类 btnToActive.classList.add('checked') btnToActive.checked = true if (focus) { themeSwitcher.focus() } }
修改说明
- 遍历所有主题切换按钮时,新增
element.checked = false,统一重置选中状态 - 找到目标主题按钮后,新增
btnToActive.checked = true,设置其为选中状态 - 保留原有的样式类操作,确保Bootstrap按钮组的视觉选中效果正常
完整修改后的JavaScript代码
(() => { 'use strict' const getStoredTheme = () => localStorage.getItem('theme') const setStoredTheme = theme => localStorage.setItem('theme', theme) const getPreferredTheme = () => { const storedTheme = getStoredTheme() if (storedTheme) { return storedTheme } return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' } const setTheme = theme => { if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) { document.documentElement.setAttribute('data-bs-theme', 'dark') } else { document.documentElement.setAttribute('data-bs-theme', theme) } } setTheme(getPreferredTheme()) const showActiveTheme = (theme, focus = false) => { const themeSwitcher = document.querySelector('#bd-theme') if (!themeSwitcher) { return } const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`) document.querySelectorAll('[data-bs-theme-value]').forEach(element => { element.classList.remove('checked') element.checked = false }) btnToActive.classList.add('checked') btnToActive.checked = true if (focus) { themeSwitcher.focus() } } window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { const storedTheme = getStoredTheme() if (storedTheme !== 'light' && storedTheme !== 'dark') { setTheme(getPreferredTheme()) } }) window.addEventListener('DOMContentLoaded', () => { showActiveTheme(getPreferredTheme()) document.querySelectorAll('[data-bs-theme-value]') .forEach(toggle => { toggle.addEventListener('click', () => { const theme = toggle.getAttribute('data-bs-theme-value') setStoredTheme(theme) setTheme(theme) showActiveTheme(theme, true) }) }) }) })()
配套HTML按钮组说明
建议移除默认的checked属性,让JavaScript自动根据存储的主题或系统偏好设置选中项:
<div class="btn-group" id="bd-theme" role="group"> <input autocomplete="off" class="btn-check" data-bs-theme-value="light" id="btnradio1" name="btnradio" type="radio"> <label class="btn btn-outline-dark" for="btnradio1"> Light </label> <input autocomplete="off" class="btn-check" data-bs-theme-value="dark" id="btnradio2" name="btnradio" type="radio"> <label class="btn btn-outline-dark" for="btnradio2"> Dark </label> <input autocomplete="off" class="btn-check" data-bs-theme-value="auto" id="btnradio3" name="btnradio" type="radio"> <label class="btn btn-outline-dark" for="btnradio3"> Auto </label> </div>
内容的提问来源于stack exchange,提问作者Robert Banks
相关产品推荐
相关产品推荐

