在 React 中如何实现亮色 / 暗色主题切换?
推荐「CSS 变量 + Context + 根节点 class」的方案,性能好、可动态换肤。
1. 用 CSS 变量定义两套主题
:root { --bg: #fff; --text: #111; }
:root.dark { --bg: #111; --text: #fff; }
.app { background: var(--bg); color: var(--text); }2. 用 Context 管理主题状态并切换根节点 class
const ThemeContext = createContext()
function ThemeProvider({ children }) {
const [theme, setTheme] = useState(
() => localStorage.getItem('theme') || 'light'
)
useEffect(() => {
document.documentElement.className = theme // 切换到 <html class="dark">
localStorage.setItem('theme', theme)
}, [theme])
return (
<ThemeContext.Provider value={{
theme,
toggle: () => setTheme(t => t === 'light' ? 'dark' : 'light')
}}>
{children}
</ThemeContext.Provider>
)
}其他方案
- CSS-in-JS(styled-components):用
ThemeProvider注入 theme 对象,适合动态主题。 - next-themes:Next.js 项目直接用,处理 SSR 闪烁(FOUC)很方便。
注意点
- 避免 SSR 闪烁:在
<head>内联一段脚本提前设置html的 class(next-themes 已处理)。 - 切换时加
transition可做平滑过渡,但注意性能。 - 组件内不要写死颜色,统一用 CSS 变量,否则换肤不生效。