preface
In the front-end field, ANTD is undoubtedly the most widely used UI class library in the React ecosystem. Antd highly encapsulates common form class input components, bringing convenience out of the box, but at the same time, it is increasingly difficult to control its style. You’ve all had the experience of being forced to modify antD styles by a product or interaction. Many times, it is difficult to pass “this is an open source control, the style is not easy to modify” prevarication past. So the question is, how to elegantly modify the style of ANTD?
The specific methods
After exploration, there are roughly the following ideas:
- Add the class name or style directly
This is the most general approach and works directly on the current element, but sometimes we find antD components end up with many levels nested in the DOM layer. Just making changes to the outer element and having the child elements inherit the style doesn’t quite cut it; The natural idea at this point is to use CSS selectors to retrieve child elements. The code logic is as follows:
import s from './index.css';
import { Input, AutoComplete } from 'antd';
/ /... Omit irrelevant code
<div className={s.feeWrap}>
<Input
disabled
value={lanWrap('Transfer fee')}
addonAfter={fee}
className={cx(s.feeInput, 'tInput')} / >
</div>
Copy the code
CSS code
.feeInput .ant-input {
background-color: #ffffff ! important;
font-size:.14rem;
color: # 555555 ! important;
user-select: none;
}
Copy the code
Now let’s test the results.
The background color of the input box did not change as we expected. Next, we will analyze the specific reasons. From the above screenshot, we can see that the CSS class name inside antD component is not processed by CSS Module, but our custom style is realized by CSS Module, resulting in dom cannot match the correct style. Let’s take a look at the webPack configuration:
module: {
rules: [{test: / (?
,
exclude: /node_modules/,
use: [
//MiniCssExtractPlugin.loader,
'style-loader',
{
loader: 'typings-for-css-modules-loader'.options: {
modules: true.namedExport: true}}]}, {// Specifically dealing with ANTD CSS styles
test: /\.(less)$/,
include: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: "less-loader".options: {
lessOptions: {
javascriptEnabled: true}}}],},]}Copy the code
As can be seen from the configuration here, the business code uses CSS moudle. Since antD components are written in less, we use less Loader to process styles here. CSS loader is not enabled for the part of LESS, so the class name is still the original class name seen in dom. Of course, if your project does not have CSS Module enabled and uses the original class name to control the style, this problem does not exist. 2. Use a variety of CSS file packaging strategies have analyzed the root of the problem, the next is how to solve the problem, the most natural idea is to use a special CSS style packaging strategy for this part of the special needs, in simple terms, for the STYLE of ANTD components, hang a regular string class name on the outside, Use a separate CSS file to control styles. At packaging time, take a special policy of not enabling CSS Modules for this file, so that it is consistent with antD component class name processing, and you can control styles directly through CSS class name selector. The WebPack configuration is as follows
module: {
rules: [{// To customize styles for ANTD, use non-fetch matches, reverse affirmative precheck, and don't use CSS Modules
// If the file name contains antD, do not enable CSS Module
test: / (? <=antd)\.(css|scss)$/,
exclude: /node_modules/,
use: [
//MiniCssExtractPlugin.loader,
'style-loader',
{
loader: 'typings-for-css-modules-loader'.options: {
modules: false.namedExport: true}}]}, {// If the file name does not contain antD, enable CSS Module
test: / (?
,
exclude: /node_modules/,
use: [
//MiniCssExtractPlugin.loader,
'style-loader',
{
loader: 'typings-for-css-modules-loader'.options: {
modules: true.namedExport: true}}]},]}Copy the code
For the antD special style file, we named it index.antd. CSS, so that it will not be processed by CSS Module, we made the following changes to the code:
import s from './index.css';
import './index.antd.css';
/ /... Omit irrelevant code
<div className={s.feeWrap}>
<Input
disabled
value={lanWrap('Transfer fee')}
addonAfter={fee}
className={cx('feeInput', 'tInput')} / >
</div>
Copy the code
In index.antd. CSS there is the following content
.feeInput .ant-input {
background-color: #ffffff ! important;
font-size:.14rem;
color: # 555555 ! important;
user-select: none;
}
Copy the code
Let’s look at the effect:
And we can see from here, the peripheralfeeInput
Class has successfully modified antD’s native through the class selector.ant-input
Style.
3. Ultimate solution
The problem is solved, but the actual operation process is too tedious, there should be an extra file, but also new Webpack packaging rules, do not meetless is more
Is there a better solution? One thing to note here is that the CSS Module is used for global styles:global
In other words, we can take advantage of this to define classes outside the ANTD component for refined control styles in:global
In this way, class name hash is avoided, and style control can be realized with antD class name rules. The specific code is as follows:
import s from './index.css';
/ /... Omit irrelevant code
<div className={s.feeWrap}>
<Input
disabled
value={lanWrap('Transfer fee')}
addonAfter={fee}
className={cx('fee11Input', 'tInput')} / >
</div>
Copy the code
Js code does not need to introduce a special index.antd. CSS file, CSS file like this:
:global(.fee11Input .ant-input) {
background-color: #ffffff ! important;
font-size:.14rem;
color: # 555555 ! important;
user-select: none;
}
Copy the code
This method, due to the limitations of CSS syntax, causes the class name to be unable to hash, and has the risk of polluting the global class roll. If SCSS, LESS, SASS and other precompiled tools are enabled, a more complete solution is this
.fee11Input {
:global {
.ant-input {
background-color: #ffffff ! important;
font-size:.14rem;
color: # 555555 ! important; user-select: none; }}}Copy the code
External code should be changed to CSS Module style
<Input
disabled
value={lanWrap('Transfer fee')}
addonAfter={fee}
className={cx(s.fee11Input)}/>
Copy the code
Let’s look at the effect:
The result is as expected, a perfect modification of the antD component’s inline style! There is no problem of introducing redundant files in the second solution, simple and efficient.