如何在Next.js中结合next-themes实现组件级SCSS主题样式?
Next.js中SCSS主题Mixin全局生效但组件级失效问题
我在Next.js应用中尝试结合SCSS与next-themes实现主题切换,全局样式里的主题mixin能正常工作,但组件级的样式无法生效。主题采用SCSS的map和mixin方案,通过next-themes切换主题。
next.config.js
const path = require('path') module.exports = { sassOptions: { includePaths: [path.join(__dirname, 'styles')], }, }
_app.js 页面
import Layout from '../components/Layout'; import { ThemeProvider } from 'next-themes' import '../styles/globals.scss'; export default function MyApp({ Component, pageProps }) { return ( <Layout> <ThemeProvider attribute="class" disableTransitionOnChange> <Component {...pageProps} /> </ThemeProvider> </Layout> ) }
Layout 组件
import Head from 'next/head'; import Header from '../Header'; import Footer from '../Footer'; import styles from './Layout.module.scss'; export default function Layout({ children }) { return ( <> <Head> <title>My title</title> <meta name="description" content="My app" /> <link rel="icon" href="/favicon.ico" /> </Head> <div className={styles.container}> <Header /> <main className={styles.main}> {children} </main> <Footer /> </div> </> ) }
_variables.scss 主题变量
/* Light Theme Colors */ $color-bg-light: #f2f2f2; $color-text-light: black; $color-link-light: #002fff; /* Dark Theme Colors */ $color-bg-dark: #001329; $color-text-dark: white; $color-link-dark: #64ff00;
_themes.scss
@import './variables'; $themes: ( dark: ( 'text-color': $color-text-dark, 'bg-color': $color-bg-dark, 'link-color': $color-link-dark ), light: ( 'text-color': $color-text-light, 'bg-color': $color-bg-light, 'link-color': $color-link-light ) ); @mixin theme() { @each $theme, $map in $themes { $theme-map: $map !global; .#{$theme} & { @content; } } $theme-map: null !global; } @function theme-get($key) { @return map-get($theme-map, $key); }
ThemeSwitch 组件
import { useState, useEffect } from 'react'; import { useTheme } from 'next-themes'; import styles from './ThemeSwitch.module.scss'; export default function ThemeSwitch() { const [mounted, setMounted] = useState(false) const { theme, setTheme } = useTheme() // useEffect仅在客户端运行,此时可以安全渲染UI useEffect(() => { setMounted(true) }, []) if (!mounted) { return null } return ( <> <div className={styles.switch}> 当前主题:{theme} <button onClick={() => setTheme('light')}>浅色模式</button> <button onClick={() => setTheme('dark')}>深色模式</button> </div> </> ) };
全局样式 globals.scss(正常生效)
@import 'variables.scss'; @import 'themes.scss'; html, body { @include theme() { color: theme-get('text-color'); background-color: theme-get('bg-color'); } } a { @include theme() { color: theme-get('link-color'); } }
组件级样式 Footer.module.scss(无法生效)
@import '../../styles/variables'; @import '../../styles/mixins'; @import '../../styles/themes'; .footer { p { font-size: $font-size--small; } a { @include theme() { color: theme-get('link-color'); } } }
内容的提问来源于stack exchange,提问作者rickhekman
相关产品推荐
相关产品推荐

