Theming Ant Design : a detailed step by step basic guide
Applying the theming guidelines provided by Ant Design’s documentation in an actual application
--
Ant Design is a very popular UI libraries for React. It provides a well designed and eminently composable collection of components.
However, it is very opinionated about styles. Its philosophy is not only to provide tools, but a whole conceptual approach for designing UIs. Depending on your needs and inclinations, this can be a massive pro, or a very irritating con.
Thankfully, Ant Design also provides a way to theme the experience they offer. This page in Ant Design’s documentation provides guidelines for making its components look more in line with a user’s brand identity. It is serviceable, but the operative word here is “guideline”: it only superficially lists approaches you can employ to make it happen. And there is no actual example of it being implemented in a real app, and the required configuration is only lightly touched upon.
This article aims to complement the docs by providing a step by step guide to theming Ant Design with their recommended approach. Possible pain points will be signaled with a ⚠️gotcha alert⚠️, and for each step, I will point to a specific commit of the repo I created for this article.
It is based on a barebone project starter I made for testing and experimentation, but any project built with Webpack and Babel where you have access to the config files will behave similarly. Theming an unejected create-react-app
project is different and arguably better documented.
If you just want to see the code, head over there now : https://github.com/mathieu-anderson/antd-theming-examples
Step 1: create project, install Ant Design and babel-plugin-import
Link to commit
- Install the
antd
package (to be able to import components from the library, as seen here).
yarn add antd
- ⚠️gotcha alert⚠️ Install the Babel plugin
babel-plugin-import
. This is only briefly mentioned in the docs, but is very important. We will explain its purpose in a second.
yarn add -D babel-plugin-import
- Configure
babel-plugin-import
in.babelrc
(see in commit). Notice that we pass“css”
as our style option. The other possible option istrue
. We will come back to it later.
"plugins": [
[
"import", {
"libraryName": "antd",
"libraryDirectory": "es",
"style": "css"
}
]
]
The purpose of babel-plugin-import
is to allow modular import of Ant Design components, so that writing this…
import { Select } from "antd";
… only imports the Select
component, not the whole Ant Design library. But more importantly, the styles
option of this plugin adds the possibility to also import the styles of the given component. This allows us to never have to import styles directly from antd
(as it is done in the component’s demo Codesandbox provided by Ant Design’s docs with import "antd/dist/antd.css";
).
This gives us an application styled with the default Ant Design theme :
Step 2: install less and less-loader, edit Webpack config, edit babel-plugin-import style option
Link to commit
Ant Design styles relies on the CSS postprocessor Less. It is made clear that the correct way to theme Ant Design is to override the default less
variables. We therefore need to be able to parse those variables, and use them in our project.
- Install
less
.
yarn add less
- Install the Webpack loader necessary to parse
less
files,less-loader
.
yarn add -D less-loader
- Add a rule to the Webpack config to appropriately parse
less
files (see in commit). ⚠️gotcha alert⚠️ Notice thejavascriptEnabled: true
option set forless-loader
: it is required to load Ant Design’sless
styles without issues.
{
test: /\.less$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader"
},
{
loader: "less-loader",
options: {
javascriptEnabled: true
}
}
}
- Change the
style
option ofbabel-plugin-import
totrue
. When we used“css”
, we were simply importing the pre-bundled CSS styles from the library as is. ⚠️gotcha alert⚠️ Withtrue
, we import the source files. This means we can modify them during the compilation step (handled by Babel and Webpack), which allows us to customize the theme.
"plugins": [
[
"import", {
"libraryName": "antd",
"libraryDirectory": "es",
"style": true
}
]
]
Nothing has changed in the looks of our app, but all the preliminary preparations are now done. We can start theming our Ant Design components!
Step 3: override less variables in Webpack config (inline)
Link to commit
Now that the configuration is correct, we can follow the official docs more easily. The first solution is to write inline configuration for our theme, in a “plain object” kind of syntax.
- Add the
modifyVars
option toless-loader
(see in commit), populated with a simple object where the keys are theless
variable to override, and the values are what we override them with. This leverages a feature of Less.
{
loader: "less-loader",
options: {
modifyVars: {
"primary-color": "green",
"link-color": "green",
"font-family": "serif"
},
javascriptEnabled: true
}
}
This override happens during the compile time, and finally we see tangible results!
This naive approach to theming might not be the most practical, though. You might want the native IDE support you get when writing actual CSS/LESS.You also might want to separate your configs better, and have something like a theme
file.
Step 4: override less variables with a theme.less file
Link to commit
- Add a
theme.less
file overriding theless
variable values from Ant Design (see in commit).
@primary-color: red; @link-color: red;
@font-family: sans-serif;
- Add
hack
key tomodifyVars
option inless-loader
. This will write an@import
for our theme file where appropriate in the source styles. ⚠️gotcha alert⚠️ Be careful to give the proper path to your.less
theme file. This syntax can be tricky (see in commit).
{
loader: "less-loader",
options: {
modifyVars: {
hack: `true; @import "${path.resolve(
__dirname,
"../",
"theme.less"
)}";`
},
javascriptEnabled: true
}
}
This is a much more robust solution for theming, and gives the same result as the previous one (with different colors and fonts).
Optional step: dealing with Ant Design’s global styles
Link to commit
You probably have noticed that everything is styled according to the theme specified we specified, not only the Ant Design components. ⚠️gotcha alert⚠️ This is because the default behavior of Ant Design is to ship a host of global styles whenever you import a component’s style. Another instance of Ant Design being very opinionated.
There are ways to avoid this, but they deserve their own article. In the meanwhile, you can directly overwrite the Ant Design styles and theme by writing your own CSS for the components you wish to have control over.
These rules let us regain control over the fonts and the links styles:
.App {
text-align: center;
margin: 0 30%;
font-family: 'Courier New', Courier, monospace;
}a {
color: blue;
font-weight: bold;
}a:hover {
color: blue;
text-decoration: underline;
}p {
margin-bottom: 3em;
}
And reach this masterpiece:
Hope this will help anyone having difficulties implementing the theming recommendations from Ant Design’s official docs. If I made any mistake please comment, or if you have other approaches to this task, please share!