WordPress实现暗黑模式白天黑夜代码版

为WordPress实现代码版的黑暗模式,核心是通过添加自定义CSS和少量JavaScript,在前端动态切换主题。以下是具体实现方案。

演示效果看本博客左下角。下面给大家详细讲解代码版实现效果和具体的说明,适适用于DIY玩家折腾和美化,自适应效果实现!

🎯 核心原理

通过 CSS自定义属性(变量) 定义明暗两套配色,利用JavaScript在网页的<html><body>标签上切换一个特定的CSS类名(如.dark-mode),从而激活对应的黑暗样式。

📝 完整实现代码

你可以将以下代码添加到你的 子主题 的functions.php文件中,或通过 “外观” > “主题文件编辑器” 进行操作(更推荐创建子主题,避免主题更新时代码丢失)。

// 1. 在主题头部添加必要的样式和脚本
function add_dark_mode_assets() {
    // 内联输出核心CSS变量和基础样式
    ?>
    <style id="dark-mode-css-vars">
        :root {
            /* 默认明亮模式变量 */
            --bg-color: #ffffff;
            --text-color: #333333;
            --link-color: #0073aa;
            --border-color: #dddddd;
        }
        .dark-mode {
            /* 黑暗模式变量覆盖 */
            --bg-color: #1a1a1a;
            --text-color: #e0e0e0;
            --link-color: #66b3ff;
            --border-color: #444444;
            /* 可选:为图像等元素添加滤镜 */
            filter: invert(1) hue-rotate(180deg);
        }
        /* 将变量应用到页面元素 */
        body {
            background-color: var(--bg-color);
            color: var(--text-color);
            transition: background-color 0.3s ease, color 0.3s ease;
        }
        a { color: var(--link-color); }
        .site-header, .widget, .comment-list { border-color: var(--border-color); }
    </style>

    <!-- 用于前端切换的按钮 -->
    <button id="dark-mode-toggle" aria-label="切换深色/浅色模式" style="position:fixed; bottom:20px; right:20px; z-index:9999; padding:10px; border-radius:50%; background:#333; color:#fff; border:none; cursor:pointer;">
        🌓
    </button>

    <?php
    // 内联输出控制逻辑JavaScript
    ?>
    <script>
        (function() {
            const toggleButton = document.getElementById('dark-mode-toggle');
            const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
            
            // 从本地存储读取用户偏好,若不存在则尝试匹配系统偏好
            let currentMode = localStorage.getItem('theme') || (prefersDarkScheme.matches ? 'dark' : 'light');
            
            // 初始应用模式
            if (currentMode === 'dark') {
                document.documentElement.classList.add('dark-mode');
                toggleButton.textContent = '☀️';
            }
            
            // 切换按钮点击事件
            toggleButton.addEventListener('click', function() {
                const isDark = document.documentElement.classList.toggle('dark-mode');
                localStorage.setItem('theme', isDark ? 'dark' : 'light');
                toggleButton.textContent = isDark ? '☀️' : '🌙';
            });
            
            // 监听系统主题变化(可选)
            prefersDarkScheme.addEventListener('change', (e) => {
                // 仅当用户未明确设置偏好时,跟随系统变化
                if (!localStorage.getItem('theme')) {
                    if (e.matches) {
                        document.documentElement.classList.add('dark-mode');
                        toggleButton.textContent = '☀️';
                    } else {
                        document.documentElement.classList.remove('dark-mode');
                        toggleButton.textContent = '🌙';
                    }
                }
            });
        })();
    </script>
    <?php
}
add_action('wp_head', 'add_dark_mode_assets');

⚙️ 关键代码解析与定制要点

  1. CSS变量定义与覆盖 (:root 和 .dark-mode):
    • --bg-color--text-color 等是自定义属性,用于集中管理颜色。
    • .dark-mode 类中重新定义了这些变量。当 <html> 元素拥有此类名时,所有使用这些变量的元素都会自动切换颜色。
  2. 控制逻辑 (<script> 内代码)
    • 本地存储:使用 localStorage 记住用户的选择。
    • 系统偏好匹配:通过 window.matchMedia('(prefers-color-scheme: dark)') 检测用户设备是否启用了深色模式,并据此设置初始状态。
    • 响应系统变化:监听系统主题变化,并在用户未主动设置时自动跟随切换。
  3. 如何适配你的主题
    • 核心:上述代码中的 --bg-color 等变量和 bodya 等选择器是通用示例。
    • 查找你主题的实际CSS选择器:在你的网站上,使用浏览器的 “检查”(Inspect)工具,查看你想改变样式的元素(如导航栏、文章卡片、按钮)的 CSS类名。例如,你的标题可能用的是 .entry-title,侧边栏可能是 #secondary
    • 替换和扩展:将示例中的通用选择器(如 .site-header)替换为你自己主题的类名,并可能需要为更多类型的元素(如按钮 .button、输入框 input)定义和应用的CSS变量。

✅ 关键检查与高级优化

  • 避免页面加载时闪烁:如果黑暗模式生效前出现短暂白屏,需将初始化脚本尽可能提前。可将上述PHP函数中的JavaScript逻辑提取为独立.js文件,并修改挂载钩子:phpfunction enqueue_dark_mode_script() { wp_enqueue_script(‘dark-mode-script’, get_stylesheet_directory_uri() . ‘/dark-mode.js’, array(), null, false); // 第三个参数为false,使脚本在<head>中加载,尽早执行 } add_action(‘wp_enqueue_scripts’, ‘enqueue_dark_mode_script’, 1); // 数字1表示高优先级
  • 性能与最佳实践
    • 将所有CSS变量定义和选择器规则,统一放入你子主题的 style.css 文件,是更规范和利于维护的做法。
    • 对于图片和视频,在黑暗模式下添加 filter 属性需谨慎,可能会影响可读性。建议针对特定类名(如 .dark-mode img)应用,或使用CSS的 mix-blend-mode 属性获得更自然的效果。

总结来说,通过代码实现黑暗模式能给你最大的控制权,但需要你根据自己主题的结构进行细致的CSS适配。如果你在查找和替换特定CSS选择器时遇到困难,可以告诉我你使用的主题名称,或者提供你的网站地址,我可以帮你分析如何更精准地覆盖样式。

🌓 WordPress代码版黑暗模式完整美化方案

下面是一个经过美化的完整黑暗模式实现代码,包含平滑过渡、现代化UI和完整的功能。将以下代码添加到你的主题functions.php文件或创建为独立插件。

<?php
/**
 * WordPress黑暗模式美化版
 * 将本代码添加到主题的functions.php文件中
 */
function enhanced_dark_mode_init() {
    // 只在前台加载,不影响管理后台
    if (is_admin()) return;
    
    // 添加CSS样式
    add_action('wp_head', 'enhanced_dark_mode_styles', 10);
    
    // 添加切换按钮和JavaScript
    add_action('wp_footer', 'enhanced_dark_mode_ui', 100);
    
    // 添加body类以便主题级控制
    add_filter('body_class', 'add_dark_mode_body_class');
}

// 添加CSS样式到头部
function enhanced_dark_mode_styles() {
    ?>
    <style id="enhanced-dark-mode-styles">
        /* ===== CSS变量定义 ===== */
        :root {
            /* 明亮模式变量 */
            --dm-bg-primary: #ffffff;
            --dm-bg-secondary: #f8f9fa;
            --dm-bg-tertiary: #e9ecef;
            --dm-text-primary: #212529;
            --dm-text-secondary: #6c757d;
            --dm-text-muted: #adb5bd;
            --dm-border-color: #dee2e6;
            --dm-primary-color: #4361ee;
            --dm-secondary-color: #3a0ca3;
            --dm-accent-color: #4cc9f0;
            --dm-card-bg: #ffffff;
            --dm-input-bg: #ffffff;
            --dm-shadow-color: rgba(0, 0, 0, 0.1);
            --dm-shadow-hover: rgba(0, 0, 0, 0.15);
            
            /* 切换按钮变量 */
            --dm-btn-size: 50px;
            --dm-btn-icon-size: 24px;
            --dm-btn-bg: var(--dm-primary-color);
            --dm-btn-color: #ffffff;
        }

        .dark-mode {
            /* 黑暗模式变量覆盖 */
            --dm-bg-primary: #121212;
            --dm-bg-secondary: #1e1e1e;
            --dm-bg-tertiary: #2d2d2d;
            --dm-text-primary: #e0e0e0;
            --dm-text-secondary: #a0a0a0;
            --dm-text-muted: #6a6a6a;
            --dm-border-color: #404040;
            --dm-primary-color: #6d8eff;
            --dm-secondary-color: #7b4dff;
            --dm-accent-color: #00d4ff;
            --dm-card-bg: #1e1e1e;
            --dm-input-bg: #2d2d2d;
            --dm-shadow-color: rgba(0, 0, 0, 0.3);
            --dm-shadow-hover: rgba(0, 0, 0, 0.4);
            
            /* 图像滤镜 - 更自然的黑暗模式效果 */
            --dm-image-filter: brightness(0.8) contrast(1.1);
        }

        /* ===== 全局样式应用 ===== */
        body {
            background-color: var(--dm-bg-primary);
            color: var(--dm-text-primary);
            transition: background-color 0.4s cubic-bezier(0.4, 0, 0.2, 1),
                        color 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        }

        /* 链接样式 */
        a {
            color: var(--dm-primary-color);
            transition: color 0.3s ease;
        }
        
        a:hover {
            color: var(--dm-accent-color);
        }

        /* 卡片和容器 */
        .post, .page, .article, .entry, .card, .widget, .comments-area,
        .site-main, .content-area, .sidebar, .nav-links,
        .wp-block-group, .wp-block-cover, .wp-block-media-text {
            background-color: var(--dm-card-bg);
            border-color: var(--dm-border-color);
            transition: background-color 0.4s cubic-bezier(0.4, 0, 0.2, 1),
                        border-color 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        }

        /* 表单元素 */
        input, textarea, select {
            background-color: var(--dm-input-bg);
            color: var(--dm-text-primary);
            border-color: var(--dm-border-color);
            transition: all 0.3s ease;
        }

        /* 按钮 */
        button:not(#dark-mode-toggle-btn), 
        .button, .btn, .wp-block-button__link,
        input[type="submit"], input[type="button"] {
            background-color: var(--dm-primary-color);
            color: white;
            border-color: var(--dm-primary-color);
            transition: all 0.3s ease;
        }

        /* 标题 */
        h1, h2, h3, h4, h5, h6, .site-title, .entry-title {
            color: var(--dm-text-primary);
        }

        /* 代码块 */
        pre, code, .wp-block-code {
            background-color: var(--dm-bg-tertiary);
            color: var(--dm-text-primary);
        }

        /* 表格 */
        table, th, td {
            border-color: var(--dm-border-color);
        }

        /* 引用 */
        blockquote, .wp-block-quote {
            border-left-color: var(--dm-primary-color);
            background-color: var(--dm-bg-secondary);
        }

        /* 图像适配 */
        .dark-mode img:not(.dark-mode-ignore),
        .dark-mode video:not(.dark-mode-ignore),
        .dark-mode iframe:not(.dark-mode-ignore) {
            filter: var(--dm-image-filter);
        }

        /* ===== 切换按钮样式 ===== */
        #dark-mode-toggle-container {
            position: fixed;
            bottom: 30px;
            right: 30px;
            z-index: 99999;
        }

        #dark-mode-toggle-btn {
            width: var(--dm-btn-size);
            height: var(--dm-btn-size);
            border-radius: 50%;
            background: var(--dm-btn-bg);
            color: var(--dm-btn-color);
            border: none;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 4px 15px var(--dm-shadow-color);
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            position: relative;
            overflow: hidden;
            font-size: var(--dm-btn-icon-size);
        }

        #dark-mode-toggle-btn:hover {
            transform: translateY(-3px) scale(1.05);
            box-shadow: 0 6px 20px var(--dm-shadow-hover);
        }

        #dark-mode-toggle-btn:active {
            transform: translateY(-1px) scale(0.98);
        }

        #dark-mode-toggle-btn .icon {
            position: absolute;
            transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55),
                       opacity 0.4s ease;
        }

        #dark-mode-toggle-btn .sun {
            opacity: 1;
            transform: rotate(0deg);
        }

        #dark-mode-toggle-btn .moon {
            opacity: 0;
            transform: rotate(-90deg);
        }

        .dark-mode #dark-mode-toggle-btn .sun {
            opacity: 0;
            transform: rotate(90deg);
        }

        .dark-mode #dark-mode-toggle-btn .moon {
            opacity: 1;
            transform: rotate(0deg);
        }

        /* 按钮波纹效果 */
        #dark-mode-toggle-btn::after {
            content: '';
            position: absolute;
            width: 100%;
            height: 100%;
            border-radius: 50%;
            background: rgba(255, 255, 255, 0.1);
            transform: scale(0);
            transition: transform 0.3s ease;
        }

        #dark-mode-toggle-btn:active::after {
            transform: scale(2);
            opacity: 0;
        }

        /* ===== 加载动画 ===== */
        .dark-mode-loading {
            opacity: 0;
        }

        .dark-mode-loaded {
            opacity: 1;
            transition: opacity 0.3s ease;
        }

        /* ===== 响应式设计 ===== */
        @media (max-width: 768px) {
            #dark-mode-toggle-container {
                bottom: 20px;
                right: 20px;
            }
            
            #dark-mode-toggle-btn {
                width: 44px;
                height: 44px;
                font-size: 20px;
            }
        }
    </style>
    <?php
}

// 添加UI元素和JavaScript
function enhanced_dark_mode_ui() {
    ?>
    <!-- 黑暗模式切换按钮 -->
    <div id="dark-mode-toggle-container">
        <button id="dark-mode-toggle-btn" aria-label="切换深色/浅色模式" title="切换深色/浅色模式">
            <span class="icon sun">☀️</span>
            <span class="icon moon">🌙</span>
        </button>
    </div>

    <!-- 通知提示(可选) -->
    <div id="dark-mode-notice" style="display:none; position:fixed; bottom:90px; right:30px; background:var(--dm-primary-color); color:white; padding:12px 20px; border-radius:10px; box-shadow:0 4px 15px rgba(0,0,0,0.2); z-index:99998; max-width:250px; font-size:14px; animation:fadeInUp 0.4s ease;">
        <span id="dark-mode-notice-text"></span>
    </div>

    <script>
    (function() {
        'use strict';
        
        // 配置
        const CONFIG = {
            storageKey: 'wp_dark_mode_preference',
            noticeDuration: 2000,
            animationDuration: 400
        };
        
        // DOM元素
        const toggleBtn = document.getElementById('dark-mode-toggle-btn');
        const noticeEl = document.getElementById('dark-mode-notice');
        const noticeText = document.getElementById('dark-mode-notice-text');
        const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
        
        // 状态管理
        let currentMode = null;
        
        // 初始化
        function initDarkMode() {
            // 检查本地存储
            const savedPreference = localStorage.getItem(CONFIG.storageKey);
            
            // 如果没有保存的偏好,检查系统偏好
            if (savedPreference === null) {
                currentMode = prefersDarkScheme.matches ? 'dark' : 'light';
            } else {
                currentMode = savedPreference;
            }
            
            // 应用初始模式
            applyMode(currentMode, false);
            
            // 标记加载完成
            document.body.classList.add('dark-mode-loaded');
            
            // 添加按钮点击事件
            toggleBtn.addEventListener('click', toggleMode);
            
            // 监听系统主题变化
            prefersDarkScheme.addEventListener('change', handleSystemThemeChange);
        }
        
        // 应用模式
        function applyMode(mode, animate = true) {
            const isDark = mode === 'dark';
            const htmlEl = document.documentElement;
            
            // 添加/移除dark-mode类
            if (isDark) {
                htmlEl.classList.add('dark-mode');
            } else {
                htmlEl.classList.remove('dark-mode');
            }
            
            // 保存到本地存储
            localStorage.setItem(CONFIG.storageKey, mode);
            
            // 更新当前状态
            currentMode = mode;
            
            // 显示通知(仅在用户手动切换时)
            if (animate) {
                showNotice(isDark ? '已切换至深色模式' : '已切换至浅色模式');
            }
        }
        
        // 切换模式
        function toggleMode() {
            const newMode = currentMode === 'dark' ? 'light' : 'dark';
            applyMode(newMode, true);
            
            // 添加点击动画
            toggleBtn.style.transform = 'scale(0.95)';
            setTimeout(() => {
                toggleBtn.style.transform = '';
            }, 150);
        }
        
        // 处理系统主题变化
        function handleSystemThemeChange(e) {
            // 仅当用户没有明确偏好时跟随系统变化
            if (!localStorage.getItem(CONFIG.storageKey)) {
                const newMode = e.matches ? 'dark' : 'light';
                applyMode(newMode, false);
                showNotice('已跟随系统切换至' + (newMode === 'dark' ? '深色' : '浅色') + '模式');
            }
        }
        
        // 显示通知
        function showNotice(message) {
            noticeText.textContent = message;
            noticeEl.style.display = 'block';
            
            setTimeout(() => {
                noticeEl.style.display = 'none';
            }, CONFIG.noticeDuration);
        }
        
        // 防止FOUT(Flash of Unstyled Text)
        document.body.classList.add('dark-mode-loading');
        
        // 页面加载完成后初始化
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', initDarkMode);
        } else {
            initDarkMode();
        }
        
        // 添加CSS动画
        const style = document.createElement('style');
        style.textContent = `
            @keyframes fadeInUp {
                from {
                    opacity: 0;
                    transform: translateY(10px);
                }
                to {
                    opacity: 1;
                    transform: translateY(0);
                }
            }
        `;
        document.head.appendChild(style);
        
    })();
    </script>
    <?php
}

// 添加dark-mode类到body标签
function add_dark_mode_body_class($classes) {
    // 这里可以通过JavaScript动态添加,但提供PHP备用方案
    return $classes;
}

// 初始化黑暗模式
add_action('init', 'enhanced_dark_mode_init');

// 添加管理栏提示(可选)
function dark_mode_admin_bar_notice($wp_admin_bar) {
    if (!current_user_can('edit_theme_options')) return;
    
    $wp_admin_bar->add_node(array(
        'id'    => 'dark-mode-info',
        'title' => '🌓 黑暗模式已启用',
        'href'  => '#',
        'meta'  => array(
            'class' => 'dark-mode-admin-notice',
            'onclick' => 'return false;'
        )
    ));
}
add_action('admin_bar_menu', 'dark_mode_admin_bar_notice', 100);
?>

🎨 自定义配置说明

1. 颜色变量调整

在CSS的:root.dark-mode部分,你可以修改颜色变量:

:root {
    --dm-primary-color: #4361ee; /* 主要品牌色 */
    --dm-bg-primary: #ffffff;    /* 主要背景色 */
    /* ... 其他变量 */
}

.dark-mode {
    --dm-primary-color: #6d8eff; /* 深色模式下的品牌色 */
    --dm-bg-primary: #121212;    /* 深色背景 */
    /* ... 其他变量 */
}

2. 按钮位置调整

修改#dark-mode-toggle-container的位置:

#dark-mode-toggle-container {
    position: fixed;
    bottom: 30px; /* 距离底部 */
    right: 30px;  /* 距离右侧 */
    /* 可以改为 left: 30px; 放到左侧 */
}

3. 特定元素排除

如果某些元素不需要黑暗模式样式,添加dark-mode-ignore类:

<img src="image.jpg" class="dark-mode-ignore" alt="不应用黑暗模式的图片">
<div class="special-widget dark-mode-ignore">特殊部件</div>

🔧 高级功能扩展

1. 添加键盘快捷键

在JavaScript部分添加:

// 支持Ctrl+Shift+D切换黑暗模式
document.addEventListener('keydown', (e) => {
    if (e.ctrlKey && e.shiftKey && e.key === 'D') {
        e.preventDefault();
        toggleMode();
        showNotice('快捷键切换: ' + (currentMode === 'dark' ? '深色模式' : '浅色模式'));
    }
});

2. 添加过渡动画优化

防止页面加载时的闪烁:

// 在functions.php最顶部添加
function dark_mode_preload() {
    if (!is_admin()) {
        $preference = isset($_COOKIE['wp_dark_mode_preference']) ? 
                     $_COOKIE['wp_dark_mode_preference'] : 'auto';
        
        if ($preference === 'dark' || 
            ($preference === 'auto' && 
             isset($_SERVER['HTTP_SEC_CH_PREFERS_COLOR_SCHEME']) &&
             $_SERVER['HTTP_SEC_CH_PREFERS_COLOR_SCHEME'] === 'dark')) {
            echo '<style>body{visibility:hidden;}</style>';
        }
    }
}
add_action('wp_head', 'dark_mode_preload', 1);

📱 响应式注意事项

代码已包含移动端适配,但需根据你的主题调整:

  1. 检查按钮位置在移动设备上是否合适
  2. 测试表单元素在黑暗模式下的显示效果
  3. 验证图像滤镜不会影响内容可读性

🚀 性能优化建议

  1. CSS压缩:生产环境移除注释和空格
  2. JavaScript延迟加载:可将脚本移到</body>
  3. 使用CSS containment:对复杂部件添加contain: paint;

🎯 检查清单

部署前请检查:

  • 所有页面类型(首页、文章页、页面、归档页)都正常
  • 表单元素(搜索框、评论框)可读性良好
  • 图像和视频不会过暗或过亮
  • 打印样式正常(添加@media print查询)
  • 与现有主题CSS无冲突

这个方案提供了美观的视觉效果和平滑的过渡动画,同时保持代码的模块化和可维护性。搞定收工,折腾笔记,记录一下。