如何让基于Antd的网站适配用户深色模式设置且切换无需刷新?
适配系统深色模式自动切换(无需页面刷新)
要实现跟随系统设置自动切换主题且无需刷新页面,核心是监听系统的颜色模式偏好变化,再同步更新Antd的主题配置:
- 用
window.matchMedia('(prefers-color-scheme: dark)')检测当前系统模式,同时通过addEventListener监听模式切换事件 - 结合React状态管理与Antd的
ConfigProvider,实时更新主题配置
示例代码:
import { useState, useEffect } from 'react'; import { ConfigProvider } from 'antd'; import { darkTheme, lightTheme } from '@ant-design/cssinjs'; function App() { const [isDarkMode, setIsDarkMode] = useState(() => { // 初始加载时检测系统当前模式 return window.matchMedia('(prefers-color-scheme: dark)').matches; }); useEffect(() => { const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handleChange = (e) => { setIsDarkMode(e.matches); }; // 添加监听 mediaQuery.addEventListener('change', handleChange); // 清理监听 return () => mediaQuery.removeEventListener('change', handleChange); }, []); return ( <ConfigProvider theme={isDarkMode ? darkTheme : lightTheme}> {/* 你的应用内容 */} </ConfigProvider> ); } export default App;
如果需要自定义主题,而非使用官方预设的darkTheme/lightTheme,可以通过切换明暗算法实现:
import { useState, useEffect } from 'react'; import { ConfigProvider } from 'antd'; import { theme } from 'antd'; const { defaultAlgorithm, darkAlgorithm } = theme; function App() { const [currentAlgorithm, setCurrentAlgorithm] = useState(() => { return window.matchMedia('(prefers-color-scheme: dark)').matches ? darkAlgorithm : defaultAlgorithm; }); useEffect(() => { const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handleChange = (e) => { setCurrentAlgorithm(e.matches ? darkAlgorithm : defaultAlgorithm); }; mediaQuery.addEventListener('change', handleChange); return () => mediaQuery.removeEventListener('change', handleChange); }, []); return ( <ConfigProvider theme={{ algorithm: currentAlgorithm }}> {/* 你的应用内容 */} </ConfigProvider> ); }
关于Antd 5.x CSS-in-JS下的主题色与@media查询问题
你的部分理解有误,具体说明:
普通CSS中使用主题色:
Antd 5.x的主题色默认仅在CSS-in-JS上下文可用,普通CSS无法直接访问,但可以通过注入CSS变量桥接:在ConfigProvider中将主题色挂载到根元素的CSS变量上,之后普通CSS即可引用这些变量。示例:
import { useState, useEffect } from 'react'; import { ConfigProvider, theme } from 'antd'; function App() { const { token } = theme.useToken(); // 挂载CSS变量到根元素 useEffect(() => { document.documentElement.style.setProperty('--primary-color', token.colorPrimary); document.documentElement.style.setProperty('--text-color', token.colorText); }, [token]); return ( <ConfigProvider> {/* 你的应用内容 */} </ConfigProvider> ); }之后在普通CSS中就能使用:
.custom-btn { background-color: var(--primary-color); color: var(--text-color); }@media查询依然适用:
- 在CSS-in-JS的样式中,可直接结合
@media (prefers-color-scheme: dark)编写适配逻辑,同时还能访问主题token:import { css } from '@ant-design/cssinjs'; const customStyle = css(({ token }) => ({ '.custom-card': { backgroundColor: token.colorBgContainer, '@media (prefers-color-scheme: dark)': { backgroundColor: token.colorBgContainer, // 自动适配深色主题下的token值 }, }, })); - 普通CSS中的
@media查询也完全不受影响,依然可用于编写系统模式适配样式。
- 在CSS-in-JS的样式中,可直接结合
内容的提问来源于stack exchange,提问作者Yann Bizeul
相关产品推荐
相关产品推荐

