The demo is based on:

React: 17.0.2

Less: 4.1.1 (if less is used)

1. Dynamically add tag custom attributes (HTML,body……)

app.tsx

import "./styles.less";

export default function App() {
	// Switch themes
	const changeTheme = (type: string) = > {
		const prefersDarkMode = window.matchMedia("(prefers-color-scheme: dark)")
			.matches; // Get whether the system is in dark mode

		if (type= = ="auto") {
			document.documentElement.setAttribute(
				"data-prefers-color",
				prefersDarkMode ? "dark" : "light"
			);
		} else {
			document.documentElement.setAttribute("data-prefers-color".type); }};return (
		<div className="App">
			<h1>Dark Light Demo</h1>
			<div>
				<button
					className="btn"
					onClick={()= > {
						changeTheme("dark");
					}}
				>
					change Dark
				</button>
			</div>
			<div>
				<button
					className="btn"
					onClick={()= > {
						changeTheme("light");
					}}
				>
					change Light
				</button>
			</div>
			<div>
				<button
					className="btn"
					onClick={()= > {
						changeTheme("auto");
					}}
				>
					change Auto
				</button>
			</div>
		</div>
	);
}

Copy the code

var.less

@c-bg: #fff;
@c-bg-dark: # 141414;
@c-text: # 141414;
@c-text-dark: rgba(255.255.255.0.65);
@c-border: #d9d9d9;
@c-border-dark: # 434343;
Copy the code

styles.less

[DATA-COLOR =”dark”]

@import "./var.less";

body {
	background: @c-bg;

	[data-prefers-color="dark"] & {
		background: @c-bg-dark; }}.App {
	font-family: sans-serif;
	text-align: center;
	color: @c-text;

	[data-prefers-color="dark"] & {
		color: @c-text-dark; }}.btn {
	margin-top: 10px;
	padding: 4px 15px;
	font-size: 14px;
	border-radius: 2px;
	color: rgba(0.0.0.0.85);
	color: @c-text;
	border: 1px solid @c-border;
	user-select: none; cursor: pointer;
	background: @c-bg;

	[data-prefers-color="dark"] & {
		color: @c-text-dark;
		border: 1px solid @c-border-dark;
		background: @c-bg-dark; }}Copy the code

2. Use CSS to customize properties (variables)

Introduction to the CSS custom properties: developer.mozilla.org/zh-CN/docs/…

app.tsx

// Replace less with CSS and keep the rest of the code the same.

- import "./styles.less";
+ import "./styles.css"; .Copy the code

styles.css

html {
	--c-bg: #fff;
	--c-text: # 141414;
	--c-border: #d9d9d9;
}

html[data-prefers-color="dark"] {
	--c-bg: # 141414;
	--c-text: rgba(255.255.255.0.65);
	--c-border: # 434343;
}

body {
	background: var(--c-bg);
}

.App {
	font-family: sans-serif;
	text-align: center;
	color: var(--c-text);
}

.btn {
	margin-top: 10px;
	padding: 4px 15px;
	font-size: 14px;
	border-radius: 2px;
	color: rgba(0.0.0.0.85);
	color: var(--c-text);
	border: 1px solid var(--c-border);
	user-select: none;
	cursor: pointer;
	background: var(--c-bg);
}

Copy the code

Can also be modified by js: document documentElement. Style. The setProperty (‘ – themeColor ‘, ‘# 333’);

3. Dynamic change <link>

Suppose the following subject directories exist:

├─ dark.css ├─ light.CSS ├─ blue.css ├─ red.css ├─ yellow.cssCopy the code
onClick = (theme) = > {
  let styleLink = document.getElementById('theme-style');
  if (styleLink) {
    // If there is a link tag with id as theme-style, modify its href directly
      styleLink.href = `/theme/${theme}.css`; // Switch themes}}else {
    // Create a new one if it does not exist
    styleLink = document.createElement('link');
    styleLink.type = 'text/css';
    styleLink.rel = 'stylesheet';
    styleLink.id = 'theme-style';
    styleLink.href = '/theme/light.css';
    }
    document.body.append(styleLink); }};Copy the code

4. Use less. ModifyVars ()

color.less

@c-bg: #fff;
@c-text: # 141414;
@c-border: #d9d9d9;
Copy the code

index.html

<! DOCTYPEhtml>
<html lang="en">.<head>
		<link rel="stylesheet/less" type="text/css" href="/color.less" />
	</head>.</html>
Copy the code

app.tsx

import "./styles.less";

const loadScript = (src: string) = > {
	return new Promise((resolve, reject) = > {
		const script = document.createElement("script");
		script.type = "text/javascript";
		script.src = src;
		script.onload = resolve;
		script.onerror = reject;
		document.head! .appendChild(script); }); };let lessLoaded = false;

export default function App() {
	// Switch themes
	const changeTheme = (type: string) = > {
    // You can automatically configure the topic by type
    
		// const prefersDarkMode = window.matchMedia("(prefers-color-scheme: dark)")
		// .matches;

		const changeColor = () = >{(window as any).less
				.modifyVars({
					"@c-bg": "# 141414"."@c-text": "Rgba (255, 255, 255, 0.65)"."@c-border": "# 434343"
				})
				.then((res) = > {
					alert("Theme changed successfully!");
				});
		};

		const lessUrl =
			"https://gw.alipayobjects.com/os/lib/less/3.10.3/dist/less.min.js";

		if (lessLoaded) {
			changeColor();
		} else{(window as any).less = {
				async: true.javascriptEnabled: true
			};
			loadScript(lessUrl).then(() = > {
				lessLoaded = true; changeColor(); }); }};return (
		/ /... Same as above...
	);
}

Copy the code
  • None of the above methods are initialized. If you need to initialize, please call the switch topic function.
  • Each of the above methods has its own advantages and disadvantages. Please choose them accordingly. If there is a better solution, please share it. 🤣 🤣 🤣