在我的項目中,我使用較少的CSS模塊,這意味著我得到了兩個世界的好處。
我的src文件夾看起來像這樣:
components/
[all components]
theme/
themes/
lightTheme.less
darkTheme.less
palette.less
調色板. less:
@import './themes/lightTheme.less';
然后,在每個想要使用主題顏色的組件中,我都這樣做:
無組件模塊:
@import '../../theme/palette.less';
.element {
background-color: @primary;
}
這個結構允許我編輯palette.less來導入我想要使用的主題。問題是,我想讓用戶自己選擇他們喜歡的主題。主題應該可以在運行時切換,這意味著我需要編譯兩個主題。
我認為完美的解決方案應該是這樣的:
無應用程序
body {
@theme: @light-theme;
&.dark-theme {
@theme: @dark-theme;
}
}
然后在每個組件中導入這個@theme變量并從中讀取屬性(即@theme[primary])。
不幸的是,較少變量的作用域不是這樣的。
我對任何使用較少模塊的解決方案持開放態度。
謝謝大家!
我知道你可能在尋找一個使用較少/ CSS模塊的解決方案,但是很有可能你的情況可以僅僅通過使用CSS變量來解決(正如Morpheus對你的問題的評論)。
它是如何工作的? 您必須確保您的所有樣式不使用硬編碼的值,即,而不是:
.awesome-div {
background-color: #fefefe;
}
你會:
:root {
--awesome-color: #fefefe;
}
.awesome-div {
background-color: var(--awesome-color);
}
在光明和黑暗之間變化 在這種方法中有兩種改變主題的方式:
使用React中的普通Js代碼來更新:root CSS元素,查看此代碼以了解更多信息。 只需在component.css文件中加載包含所有new :root變量的組件; 在React中(也是在普通CSS中),你可以很容易地讓多個組件/元素聲明它們自己的:根在它們的。css文件。
此外,任何新的:root都將覆蓋以前的:root中的沖突值。例如,如果在app.css文件中我們有:root {-color:red;}當加載另一個組件時,例如組件A,在component_a.css中我們覆蓋了相同的變量,例如:root {-color:blue;}在我們的瀏覽器中呈現的將是來自組件a的那個。
按照這個邏輯,您可以擁有一個不做任何事情也不呈現任何內容的虛擬組件,但是在這個component.js文件中,您可以導入。主題的css,例如:
import './light.css'; // suppose this is the light-theme dummy component
當在你的應用程序中切換主題時,你只需要從場景中移除虛擬組件并調用另一個組件。
我對codepen還不太熟悉,無法在那邊給你提供一個包含導入/模塊的例子,但是我希望上面的解釋能讓你明白我的意思。不過,這里有一段簡短的偽代碼,是我打算演示的內容:
loadTheme() {
if (this.state.theme === 'dark') return <LightTheme />;
if (this.state.theme === 'user-3232') return <UserTheme />;
return <DarkTheme />;
}
render() {
return (
<App>
{this.loadTheme()}
<OtherContent>
</App>
);
}
你需要使用css變量,一個簡單的選擇是使用react-theme-change庫。
示例:
主題. ts
import ReactThemeChange from 'react-theme-change';
const base = {
btn_radius: '50%',
};
const themes = {
dark: {
bg_0: 'rgba(21, 14, 65, 1)',
title: 'rgba(255, 255, 255, 1)',
},
light: {
bg_0: 'rgba(239, 242, 247, 1)',
title: 'rgba(42, 49, 60, 1)',
},
gray: {
bg_0: 'rgba(35, 42, 63, 1)',
title: 'rgba(255, 255, 255, 1)',
},
};
const useThemeChange = ReactThemeChange({
base,
themes,
defaultTheme: 'light',
});
export default useThemeChange;
風格
button {
width: 50px;
height: 50px;
border-radius: var(--btn_radius);
cursor: pointer;
}
.demo {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
gap: 12px;
align-items: center;
background-color: var(--bg_0);
color: var(--title);
}
.themeName {
font-size: 40px;
}
.btns {
display: flex;
gap: 8px;
}
轉換
import React from 'react';
import useThemeChange from './themes';
import './App.scss';
function App() {
const {theme, setTheme} = useThemeChange();
return (
<div className="demo">
<div className="themeName">current theme: {theme.name}</div>
<div className="btns">
<button onClick={() => setTheme('dark')}>dark</button>
<button onClick={() => setTheme('light')}>light</button>
</div>
</div>
);
}
export default App;
檢查樣式組件,它可以做到這一點。
https://www.npmjs.com/package/styled-components
https://styled-components.com/docs/advanced#theming
我在我的一個應用程序中把它當成復活節彩蛋來做,所以我知道它肯定有效。不幸的是,它是封閉的,所以我不能公開給你看代碼。
感謝貢獻一個堆棧溢出的答案!
請務必回答問題。提供詳細信息并分享您的研究!但是要避免…
尋求幫助、澄清或回應其他答案。根據意見發表聲明;用參考資料或個人經歷來支持他們。要了解更多,請查看我們關于撰寫精彩答案的提示。