为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');
⚙️ 关键代码解析与定制要点
- CSS变量定义与覆盖 (
:root和.dark-mode):--bg-color、--text-color等是自定义属性,用于集中管理颜色。.dark-mode类中重新定义了这些变量。当<html>元素拥有此类名时,所有使用这些变量的元素都会自动切换颜色。
- 控制逻辑 (
<script>内代码):- 本地存储:使用
localStorage记住用户的选择。 - 系统偏好匹配:通过
window.matchMedia('(prefers-color-scheme: dark)')检测用户设备是否启用了深色模式,并据此设置初始状态。 - 响应系统变化:监听系统主题变化,并在用户未主动设置时自动跟随切换。
- 本地存储:使用
- 如何适配你的主题:
- 核心:上述代码中的
--bg-color等变量和body、a等选择器是通用示例。 - 查找你主题的实际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适配。如果你在查找和替换特定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);
📱 响应式注意事项
代码已包含移动端适配,但需根据你的主题调整:
- 检查按钮位置在移动设备上是否合适
- 测试表单元素在黑暗模式下的显示效果
- 验证图像滤镜不会影响内容可读性
🚀 性能优化建议
- CSS压缩:生产环境移除注释和空格
- JavaScript延迟加载:可将脚本移到
</body>前 - 使用CSS containment:对复杂部件添加
contain: paint;
🎯 检查清单
部署前请检查:
- 所有页面类型(首页、文章页、页面、归档页)都正常
- 表单元素(搜索框、评论框)可读性良好
- 图像和视频不会过暗或过亮
- 打印样式正常(添加
@media print查询) - 与现有主题CSS无冲突
这个方案提供了美观的视觉效果和平滑的过渡动画,同时保持代码的模块化和可维护性。搞定收工,折腾笔记,记录一下。