Antd Dynamic Theme
The demo warehouse
The original post links
Plan the point
- Use the ANTD-theme-generator plug-in
- To give up
css-module
(this plug-in is not supported), use it insteadCSS-BEM
steps
1. Install dependencies
Yarn add @craco/craco craco-antd [email protected] -d yarn add less antd@^3Copy the code
Since the project uses antd@3, you need to install the specified version [email protected]. If you install the latest version, an error will be reported.
If antd@4 is used, install the antD-theme-Generator of the latest version.
2. Create a variable definition file
src/styles/variables.less
This file contains all antD defined variables (functions) as well as custom variables within the project
// We need to introduce the antd variable first
@import '~antd/lib/style/themes/default.less';
// Configure the antD topic variable with default values
@primary-color: rgb(42.187.103);
// Project internal variables (do not conflict with antD variables)
@theme-color: rgb(42.187.103);
Copy the code
3. Create a script file
scripts/color.js
This file is used to generate less style files that can be run in production mode
// AntD theme color file generation script
const fs = require('fs')
const path = require('path')
const { generateTheme } = require('antd-theme-generator')
const themeVariables = ['@primary-color'.'@theme-color']
// Because the [email protected] library is different, version 1.2.6 is required
const options = {
// AntD library path
antDir: path.join(__dirname, '.. /node_modules/antd'),
// The root of all less files to retrieve
stylesDir: path.join(__dirname, '.. /src'),
// Custom variable files
varFile: path.join(__dirname, '.. /src/styles/variables.less'),
// Which variable values need to be dynamically modified
themeVariables,
}
// Since much of the style content extracted by the plug-in is redundant, the plug-in's default export function is not used
// You need to process the data first and then export the file yourself
generateTheme(options)
.then((less) = > {
console.log("Less file contents extracted successfully");
// The location of the generated less
const outputFilePath = path.join(__dirname, ".. /public/color.less");
let content = less.replace(/([,{])\n/g."$1");
const arr = content
.split("\n")
.map((str) = > str.trim())
.filter((str) = > {
// Pure class style or variable definition
const isClassStyleOrVars =
/ ^ \. (? ! (\ \)). * \ {*? \}$/gm.test(str) || / ^ @. *? :. *? ; $/gm.test(str);
// The string does not contain arbitrary subject variables
const excludeThemeVars = themeVariables
.map((k) = > k.slice(1))
.every((k) = >! str.includes(k));// There are other redundancies, but they don't matter much
return! (isClassStyleOrVars && excludeThemeVars); }); content = arr.join("\n");
fs.writeFileSync(outputFilePath, content);
console.log("Theme style file compiled successfully");
})
.catch((error) = > {
console.log("Error", error);
});
Copy the code
4. Pack the configuration
Purpose: To have the framework support less; And introduce antD style files (less)
Since the project was generated based on create-React -app and did not want to use YARN eject, craco was used for custom configuration.
Of course, other methods can be used, as long as the ANTD components work properly.
New craco. Config. Js
const CracoAntDesignPlugin = require("craco-antd");
module.exports = {
plugins: [
// AntD is loaded on demand (instead of using this plugin, global import ANTD style is also ok)
{
plugin: CracoAntDesignPlugin,
options: {
babelPluginImportOptions: {
libraryName: "antd".libraryDirectory: "es".style: true,},},},],};Copy the code
Modify the package. The json
{
"scripts": {
"dev": "node ./scripts/color.js && craco start"."build": "node ./scripts/color.js && craco build"."color": "node ./scripts/color.js",}}Copy the code
Run the project first to check whether the configuration is successful
yarn dev
Copy the code
5. Modify the index. HTML entry file
public/index.html
<! DOCTYPE html> <html lang="en">
<head>
<meta charset="utf-8" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"/> </head> <body> <! -- antd theme less --> <link rel="stylesheet" type="text/less" href="%PUBLIC_URL%/color.less" />
<script>
// https://less.bootcss.com/usage/#browser-usage-setting-options
window.less = { javascriptEnabled: true, logLevel: 3 } </script> <! -- antd theme less end --> <noscript>You need toenable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
Copy the code
Pay attention to
The imported less tag needs to be written under the body tag, otherwise it will be overwritten by the dynamically imported style file (CSS weights issue)
6. Import less in the project entry file
scr/index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
// Introduce less to initialize the topic configuration
import 'less'
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>.document.getElementById('root'));Copy the code
7. Run the command to view the result
yarn color
yarn dev
Copy the code
After yarn Color is run, a public/color.less file is generated, and a CSS style label is automatically generated based on this less file during initialization of the running project
8. Change theme colors dynamically
Use less.modifyVars() to modify the less variable. A component is provided for your reference.
import React, { useCallback } from 'react'
import { Button, DatePicker, Pagination } from 'antd'
import less from 'less'
const colors = ['#a12356'.'#0215a6'.'#f120a1']
const ThemeSetter = () = > {
const onColorChange = useCallback((color) = > {
less.modifyVars({
'@primary-color': color,
'@theme-color': color,
})
}, [])
return (
<>
<h1>color setter</h1>
{colors.map((c) => (
<button key={c} onClick={()= > onColorChange(c)}>
{c}
</button>
))}
<hr />
<Button>A</Button>
<Button type='primary'>A</Button>
<DatePicker />
<Pagination total={100} />
</>)}export default ThemeSetter
Copy the code
conclusion
Let’s go through the principles. First, make sure your project compiles less style files and introduces ANTD as normal.
Core file scripts/color.js; public/color.less
- Based on configuration items
varFile: path.join(__dirname, '.. /src/styles/variables.less')
Find all the less variables you need to track - from
antDir: path.join(__dirname, '.. /node_modules/antd')
The antD library file specified in the configuration item traverses all less files and extracts all containsVariables to be tracked
(mainly ANTD) code - from
stylesDir: path.join(__dirname, '.. /src')
The path specified in the configuration item traverses all less files and extracts all containsVariables to be tracked
(mostly custom) code - generate
public/color.less
file public/index.html
Refer to thepublic/color.less
; And when the page is initialized, passless
To compile the correspondingcss
Style.- In the page, antD components or components that use theme variables are first rendered using compiled CSS styles from less files introduced in the component, and then rendered by
public/color.less
The compiled styles are overwritten and re-rendered. Achieve the effect of modifying the color style - In the meantime, through
less.modifyVars()
Compile the new style again, overwrite the style again and render. To achieve dynamic modification of the theme color function
Note that each time you modify or add a custom variable or style file, you need to execute YARN Color to regenerate the theme file. In a development environment, however, this is typically done only once before packaging.