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

如何用按钮切换Highlight.js代码高亮明暗主题?求更优实现方案

优化highlight.js主题切换的几种高效方案

你的实现已经能正常运行,但存在一个小bug:if分支未添加花括号,导致currentTheme = "dark"语句会无条件执行,先把这个问题修复后,再给你几个更高效、可维护的实现思路:

1. 用配置对象统一管理主题

把主题URL集中存放在配置对象中,避免硬编码,后续新增主题时只需修改配置,扩展性更强:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>highlight.js</title>
    <link rel="stylesheet" id="theme-link" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script>
    <script>
        hljs.highlightAll();

        // 统一管理主题信息
        const themes = {
            light: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css",
            dark: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/tomorrow-night-blue.css"
        };
        let currentTheme = "light";

        function toggleTheme() {
            const themeLink = document.getElementById("theme-link");
            currentTheme = currentTheme === "light" ? "dark" : "light";
            themeLink.href = themes[currentTheme];
        }
    </script>
</head>
<body>
    <pre><code class="language-python">print("Hello World!");</code></pre>
    <pre><code class="language-python">print("Hello World!");</code></pre>
    <button onclick="toggleTheme()">Toggle theme</button>
</body>
</html>

2. 用localStorage记住用户选择

将用户最后一次选择的主题存入本地存储,下次打开页面时自动加载,提升用户体验:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>highlight.js</title>
    <link rel="stylesheet" id="theme-link" href="">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script>
    <script>
        hljs.highlightAll();

        const themes = {
            light: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css",
            dark: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/tomorrow-night-blue.css"
        };
        const themeLink = document.getElementById("theme-link");
        // 优先级:本地存储 > 默认浅色主题
        let currentTheme = localStorage.getItem("hljs-theme") || "light";

        // 初始化主题
        themeLink.href = themes[currentTheme];

        function toggleTheme() {
            currentTheme = currentTheme === "light" ? "dark" : "light";
            themeLink.href = themes[currentTheme];
            localStorage.setItem("hljs-theme", currentTheme);
        }
    </script>
</head>
<body>
    <pre><code class="language-python">print("Hello World!");</code></pre>
    <pre><code class="language-python">print("Hello World!");</code></pre>
    <button onclick="toggleTheme()">Toggle theme</button>
</body>
</html>

3. 预加载主题CSS,消除切换延迟

提前加载所有主题的CSS文件,通过禁用/启用样式表实现切换,避免每次切换时的网络请求延迟:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>highlight.js</title>
    <!-- 预加载两个主题,默认禁用深色主题 -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/tomorrow-night-blue.css" id="dark-theme" disabled>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script>
    <script>
        hljs.highlightAll();

        const lightTheme = document.querySelector('link[href*="default.min.css"]');
        const darkTheme = document.getElementById("dark-theme");
        let isDark = false;

        function toggleTheme() {
            isDark = !isDark;
            lightTheme.disabled = isDark;
            darkTheme.disabled = !isDark;
        }
    </script>
</head>
<body>
    <pre><code class="language-python">print("Hello World!");</code></pre>
    <pre><code class="language-python">print("Hello World!");</code></pre>
    <button onclick="toggleTheme()">Toggle theme</button>
</body>
</html>

4. 结合系统明暗偏好自动适配

通过window.matchMedia检测系统的明暗模式偏好,自动设置初始主题,同时保留手动切换的能力:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>highlight.js</title>
    <link rel="stylesheet" id="theme-link" href="">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script>
    <script>
        hljs.highlightAll();

        const themes = {
            light: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css",
            dark: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/tomorrow-night-blue.css"
        };
        const themeLink = document.getElementById("theme-link");
        let currentTheme;

        // 检测系统明暗偏好
        const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
        // 优先级:本地存储 > 系统偏好 > 默认浅色
        currentTheme = localStorage.getItem("hljs-theme") || (prefersDark ? "dark" : "light");
        themeLink.href = themes[currentTheme];

        function toggleTheme() {
            currentTheme = currentTheme === "light" ? "dark" : "light";
            themeLink.href = themes[currentTheme];
            localStorage.setItem("hljs-theme", currentTheme);
        }

        // 可选:监听系统偏好变化,未手动设置时自动跟随
        window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
            if (!localStorage.getItem("hljs-theme")) {
                currentTheme = e.matches ? "dark" : "light";
                themeLink.href = themes[currentTheme];
            }
        });
    </script>
</head>
<body>
    <pre><code class="language-python">print("Hello World!");</code></pre>
    <pre><code class="language-python">print("Hello World!");</code></pre>
    <button onclick="toggleTheme()">Toggle theme</button>
</body>
</html>

额外小提示

  • 原代码中<pre>和<code>标签内的多余缩进会导致代码显示时带不必要的空格,建议将代码紧贴标签书写,如上述示例所示。
  • 如果需要支持更多主题,只需在themes配置对象中新增键值对即可,无需修改切换逻辑。

内容的提问来源于stack exchange,提问作者codebysumit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:44:52