You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

纯JS实现HTML页三主题切换与明暗模式切换

纯JS实现Markdown预览主题/明暗模式切换

核心规则遵循

  • 所有主题类、明暗模式类必须挂载到<html>根元素(即CSS:root匹配节点),禁止挂载到body或其他子容器,避免选择器匹配失败加载错误的Iti主题配色
  • 类名切换仅移除同组(主题组/明暗组)的旧类,根元素原有其他类(如浏览器扩展注入类、自定义功能类)全部保留,不得清空重置
  • 类名组合严格符合要求:主题类+明暗类同级共存,例如Empresas暗色模式对应根元素class为voxel-theme-empresas vscode-dark

页面控件示例

先在页面中加入切换用的下拉框和按钮:

<select id="themeSelect">
  <option value="voxel-theme-empresas">Empresas主题</option>
  <option value="voxel-theme-ion">Ion主题</option>
  <option value="voxel-theme-iti">Iti主题</option>
</select>
<button id="modeToggle">切换明暗模式</button>

CSS变量定义示例

按根元素类组合定义对应主题的全局变量即可:

/* Empresas主题 */
:root.voxel-theme-empresas.vscode-light {
  --primary: #165DFF;
  --bg: #ffffff;
  --text: #1d2129;
}
:root.voxel-theme-empresas.vscode-dark {
  --primary: #4080FF;
  --bg: #1d2129;
  --text: #f2f3f5;
}

/* Ion主题 */
:root.voxel-theme-ion.vscode-light {
  --primary: #00B42A;
  --bg: #f7f8fa;
  --text: #1d2129;
}
:root.voxel-theme-ion.vscode-dark {
  --primary: #00C440;
  --bg: #17171a;
  --text: #f2f3f5;
}

/* Iti主题 */
:root.voxel-theme-iti.vscode-light {
  --primary: #F53F3F;
  --bg: #ffffff;
  --text: #333333;
}
:root.voxel-theme-iti.vscode-dark {
  --primary: #F76560;
  --bg: #232324;
  --text: #f2f3f5;
}

完整JS逻辑

替换原有错误的switchMode实现,加入主题切换逻辑,支持本地存储记忆用户选择:

const root = document.documentElement;
// 合法类名配置
const THEME_LIST = ['voxel-theme-empresas', 'voxel-theme-ion', 'voxel-theme-iti'];
const MODE_LIST = ['vscode-light', 'vscode-dark'];
// 本地存储key
const THEME_STORAGE = 'md_preview_theme';
const MODE_STORAGE = 'md_preview_mode';

// 切换主题
function switchTheme(targetTheme) {
  if (!THEME_LIST.includes(targetTheme)) return;
  // 仅移除旧主题类,保留其他类
  THEME_LIST.forEach(cls => cls !== targetTheme && root.classList.remove(cls));
  root.classList.add(targetTheme);
  localStorage.setItem(THEME_STORAGE, targetTheme);
  // 同步下拉框状态
  const select = document.getElementById('themeSelect');
  select && (select.value = targetTheme);
}

// 切换明暗模式(修正原有操作body的错误逻辑)
function switchMode(forceDark) {
  const isDark = root.classList.contains('vscode-dark');
  const targetDark = typeof forceDark === 'boolean' ? forceDark : !isDark;
  // 仅移除旧模式类
  MODE_LIST.forEach(cls => root.classList.remove(cls));
  root.classList.add(targetDark ? 'vscode-dark' : 'vscode-light');
  localStorage.setItem(MODE_STORAGE, targetDark ? 'dark' : 'light');
}

// 初始化
function init() {
  // 读取本地存储配置,默认Empresas主题+亮色模式
  const savedTheme = localStorage.getItem(THEME_STORAGE) || 'voxel-theme-empresas';
  const savedMode = localStorage.getItem(MODE_STORAGE) || 'light';
  switchTheme(savedTheme);
  switchMode(savedMode === 'dark');

  // 绑定事件
  document.getElementById('themeSelect')?.addEventListener('change', e => switchTheme(e.target.value));
  document.getElementById('modeToggle')?.addEventListener('click', () => switchMode());
}

// DOM就绪后执行初始化
document.readyState === 'loading' 
  ? document.addEventListener('DOMContentLoaded', init)
  : init();

验证方式

切换任意主题+明暗组合后,打开开发者工具查看<html>根标签的class属性,确认类名组合符合预期,且原有class未被清除,页面读取的CSS变量与当前选中主题匹配,不会错误加载Iti主题配色即可。


内容的提问来源于stack exchange,提问作者Oo'-

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 09:36:16