如何在使用Ant Design与next-with-less的Next.js项目中添加主题切换器?
Next.js + Ant Design + Less 亮暗主题切换实现方案
步骤1:调整 next.config.js 配置
新增less变量绑定配置,将Ant Design内置主题变量统一关联到CSS自定义属性,支持客户端动态切换:
const withLess = require("next-with-less"); module.exports = withLess({ reactStrictMode: false, lessLoaderOptions: { lessOptions: { modifyVars: { // 绑定Ant Design变量到CSS自定义属性 "primary-color": "var(--primary-color)", "link-color": "var(--link-color)", "success-color": "var(--success-color)", "warning-color": "var(--warning-color)", "error-color": "var(--error-color)", "font-size-base": "var(--font-size-base)", "heading-color": "var(--heading-color)", "text-color": "var(--text-color)", "text-color-secondary": "var(--text-color-secondary)", "disabled-color": "var(--disabled-color)", "border-radius-base": "var(--border-radius-base)", "border-color-base": "var(--border-color-base)", "box-shadow-base": "var(--box-shadow-base)", "body-background": "var(--body-background)", "component-background": "var(--component-background)", }, javascriptEnabled: true, }, }, });
步骤2:修改 global.less 新增暗色主题变量
保留原有亮色主题变量,新增暗色主题下的对应变量值:
@import "~antd/dist/antd.less"; @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@200;400;700&display=swap"); // 固定公共变量 @border-radius-base: 10px; @font-size-base: 14px; // 亮色主题变量 :root { --primary-color: #26695c; --light-primary-color: #e5edef; --link-color: #1890ff; --success-color: #52c41a; --warning-color: #faad14; --error-color: #f5222d; --heading-color: rgba(0, 0, 0, 0.85); --text-color: rgba(0, 0, 0, 0.65); --text-color-secondary: rgba(0, 0, 0, 0.45); --disabled-color: rgba(0, 0, 0, 0.25); --border-color-base: #d9d9d9; --box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15); --body-background: #f3f5fa; --component-background: #ffffff; --shadow-base: var(--box-shadow-base); } // 暗色主题变量 html.dark { --primary-color: #4ca897; --light-primary-color: #1a3d36; --link-color: #40a9ff; --success-color: #73d13d; --warning-color: #ffc53d; --error-color: #ff4d4f; --heading-color: rgba(255, 255, 255, 0.85); --text-color: rgba(255, 255, 255, 0.65); --text-color-secondary: rgba(255, 255, 255, 0.45); --disabled-color: rgba(255, 255, 255, 0.25); --border-color-base: #434343; --box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.45); --body-background: #121212; --component-background: #1e1e1e; --shadow-base: var(--box-shadow-base); } html, body { font-family: "Poppins", sans-serif; background: var(--body-background); transition: background 0.3s ease; } #__next { height: 100%; } .ant-btn { display: flex; align-items: center; } .ant-btn span { margin-left: 5px; margin-right: 5px; } .ant-card .ant-card-cover { width: 100%; }
步骤3:实现主题状态全局管理
新建contexts/ThemeContext.js文件实现状态持久化与切换逻辑:
import { createContext, useContext, useEffect, useState } from 'react'; const ThemeContext = createContext(); export function ThemeProvider({ children }) { const [theme, setTheme] = useState('light'); // 初始化读取本地存储或系统主题偏好 useEffect(() => { const savedTheme = localStorage.getItem('theme'); const preferDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const initTheme = savedTheme || (preferDark ? 'dark' : 'light'); setTheme(initTheme); document.documentElement.classList.toggle('dark', initTheme === 'dark'); }, []); // 切换主题方法 const toggleTheme = () => { const newTheme = theme === 'light' ? 'dark' : 'light'; setTheme(newTheme); localStorage.setItem('theme', newTheme); document.documentElement.classList.toggle('dark', newTheme === 'dark'); }; return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); } export function useTheme() { return useContext(ThemeContext); }
修改_app.js全局包裹主题Provider:
import { ThemeProvider } from '../contexts/ThemeContext'; import '../styles/global.less'; function MyApp({ Component, pageProps }) { return ( <ThemeProvider> <Component {...pageProps} /> </ThemeProvider> ); } export default MyApp;
步骤4:添加主题切换按钮
在仪表板导航栏对应位置插入切换按钮即可:
import { Button } from 'antd'; import { SunOutlined, MoonOutlined } from '@ant-design/icons'; import { useTheme } from '../contexts/ThemeContext'; export default function ThemeToggleButton() { const { theme, toggleTheme } = useTheme(); return ( <Button type="text" icon={theme === 'light' ? <MoonOutlined /> : <SunOutlined />} onClick={toggleTheme} > {theme === 'light' ? '切换暗色' : '切换亮色'} </Button> ); }
内容的提问来源于stack exchange,提问作者Musawer Shah
相关产品推荐
相关产品推荐

