Welcome to follow my public 睿Talk
to get my latest articles:
I. Introduction
This article will introduce several common schemes for web front-end theme switching. The sample code is based on the React framework. Stop talking nonsense, show you the code!
2. Scenario 1: Predefined themes
The more common situation of this kind of scene is to pre-define two themes of light color and dark color, and there are two implementation schemes.
Scenario 1: CSS property override
This scheme takes advantage of the precise matching of CSS multi-layer styles, and realizes the switching of themes through style coverage.
First, you need to set a class
in the root element of the application, and assign the corresponding value to class
when switching themes. Take theme1/theme2 as an example below.
h2 {
color: brown;
}
button {
background-color: yellow;
}
.theme2 h2 {
color: blue;
}
.theme2 button {
background-color: green;
}
import './combine.css';
export default function App() {
const [theme, setTheme] = useState('theme1');
return (
// 切换应用根元素的 class
<div className={theme}>
<h2>{theme}</h2>
<button onClick={() => {
setTheme(theme => { if (theme === 'theme1') return 'theme2'; return 'theme1' })
}}>切换主题</button>
</div>
);
}
Option 2: CSS variable substitution
This scheme is similar to the idea of scheme 1, the difference is that css variables are used to define the theme color.
First define a dataset
: <html lang="en" data-theme="theme1">
on the root element of the page.
Then define variable values for different themes:
<style id="theme-var">
:root {
--font-color: brown;
--button-color: yellow;
}
:root[data-theme=theme2] {
--font-color: blue;
--button-color: green;
}
</style>
h2 {
color: var(--font-color, black)
}
button {
background-color: var(--button-color, gray);
}
import './var.css';
export default function App() {
const [theme, setTheme] = useState('theme1');
return (
<div>
<h2>{theme}</h2>
<button onClick={() => {
const doc = document.documentElement;
const newTheme = theme === 'theme1' ? 'theme2' : 'theme1';
// 设置页面根元素的 dataset
doc.dataset.theme = newTheme;
setTheme(newTheme);
}}>切换主题</button>
</div>
);
}
3. Scenario 2: Allow users to customize themes
The biggest difference between this scenario and scenario 1 is that CSS properties and variables cannot be predefined. Generally, it is necessary to match the interface to realize the function of dynamic replacement. The following example only demonstrates the principle, ignoring the processing of interface data.
Option 1: Full replacement of CSS
This solution is relatively simple and rude. It needs to package all the css of the page together and put it in the style
tag with a predefined ID, and replace all the css when switching themes.
// 假设下面的 css 是从接口获取的字符串
const themeAll1 = 'h2 {color: brown;} button {background-color: yellow;}'
const themeAll2 = 'h2 {color: blue;} button {background-color: green;}'
export default function App() {
const [theme, setTheme] = useState('主题1');
return (
<div>
<h2>{theme}</h2>
<button onClick={() => {
// 替换 style 标签的内容
if (theme === '主题1') {
document.getElementById('theme-all').innerText = themeAll2;
setTheme('主题2')
} else {
document.getElementById('theme-all').innerText = themeAll1;
setTheme('主题1')
}
}}>切换主题</button>
</div>
);
}
Scenario 2: CSS Variable Substitution
Scheme 1 is relatively simple and crude, and the amount of data is relatively large. You can use css variables for optimization, extract theme color variables, and put them under the root pseudo-class. When switching themes, you only need to dynamically set the value of the css variable in the style
tag.
<style id="theme-var">
:root {
--font-color: brown;
--button-color: yellow;
}
</style>
h2 {
color: var(--font-color, black)
}
button {
background-color: var(--button-color, gray);
}
import './var.css';
// 假设下面的 css 是从接口获取的字符串
const themeVar1 = ':root {--font-color: brown; --button-color: yellow;}'
const themeVar2 = ':root {--font-color: blue; --button-color: green;}'
export default function App() {
const [theme, setTheme] = useState('主题1');
return (
<div>
<h2>{theme}</h2>
<button onClick={() => {
// 替换 style 标签的内容
if (theme === '主题1') {
document.getElementById('theme-var').innerText = themeVar2;
setTheme('主题2')
} else {
document.getElementById('theme-var').innerText = themeVar1;
setTheme('主题1')
}
}}>切换主题</button>
</div>
);
}
6. Summary
This article introduces 4 commonly used theme switching schemes, the last of which is the most flexible and can be used to expand an unlimited number of themes with the API. For the more common light and dark themes, option 2 is available. What they have in common is the use of css variables to extract theme colors, which is very elegant.
My blog will be synced to Tencent Cloud + Community, and I invite everyone to join: https://cloud.tencent.com/developer/support-plan?invite_code=i2m8h47p6s31
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。