Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Theming Ant Design with Sass and Webpack

Theming Ant Design with Sass and Webpack

This is a solution on how to theme/customize Ant Design (which is written in Less) with Sass and webpack. Ant itself offers two solutions and a related article on theming, but these are only applicable if you use Less, the antd-init boilerplate or dva-cli.

What this solution offers:

  • use a single sass-file to customize (no duplicate variables for your project and Ant)
  • hot reload compatibility
  • no dependencies on outdated npm modules
  • easy integration with your existing webpack setup (webpack 3+ tested)

Any downsides?

  • all ant-styles are imported

According to our observations this does not have that much impact in practice, as using only a couple of Ant components will already result in most styles being loaded.

Procedure

The main procedure is as follows:

  1. Define your variables in variables.scss
  2. Write a ant.less file which imports the Ant less-styles and your sass-variables (yes)
  3. Tell webpack to load less files via less-loader
  4. Tell webpack to rewrite sass-files which are imported from less-files ($something -> @something)
  5. Import ant.less in your project.

How?

Apply the changes / create the files as shown below. The changes should be self-explanatory. Just keep in mind, that your exact webpack-setup may differ a bit from the one given below.

Authors: Kruemelkatze, mrukas

//Use .babelrc or add the options to the webpack loader
//Remove comments in .babelrc as they most likely will produce build errors
{
"presets": [
//...
],
"plugins": [
//...
["import", {
"libraryName": "antd",
"libraryDirectory": "es" //or "lib" for default
//No "style" setting
}]
]
}
@import "~antd/dist/antd.less";
@import "variables.scss"; // <-- SASS in a LESS file!
// Import the ant.less file in your project
import 'ant.less';
// This loader will simply replace all $something sass-variable with @something less-variables
module.exports = function (source) {
return source.replace(/\$/ig, '@');
};
// THIS FILE SHOULD ONLY CONTAIN VARIABLE DEFINITIONS
// Ant Colors & Styles can be overwritten here. Just use the variable names from
// https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
// Be sure to use $xyz, not @xyz!
$primary-color: crimson;
module: {
rules: [
{
loader: 'babel-loader',
test: /\.jsx?$/,
// Other settings, like include or exclude
options: {
presets: [
//...
],
plugins: [
// ...
// Importing Ant here is not needed if you are using a .babelrc file
['import', {
"libraryName": "antd",
"libraryDirectory": "es" // or "lib" for default
// No "style" setting
}],
]
},
},
// ...
// Include less-loader (exact settings may deviate depending on your building/bundling procedure)
{
test: /\.less$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{
loader: "less-loader",
options: {
javascriptEnabled: true //This is important!
}
}
]
},
// Tell the DEFAULT sass-rule to ignore being used for sass imports in less files (sounds weird)
{
test: /\.scss$/,
issuer: {
exclude: /\.less$/,
},
// ... other settings
},
// Define a second rule for only being used from less files
// This rule will only be used for converting our sass-variables to less-variables
{
test: /\.scss$/,
issuer: /\.less$/,
use: {
loader: './sassVarsToLess.js' // Change path if necessary
}
},
// ...
]
}
@tim-soft

This comment has been minimized.

Show comment
Hide comment
@tim-soft

tim-soft Mar 28, 2018

Hey that's pretty clever! I integrated this into a boilerplate to test with and seems to work pretty well, have you ran into any stability issues/crashes during HMR?

Here's a demo for anyone interested
https://github.com/tim-soft/react-starter-kit-antd

git clone https://github.com/tim-soft/react-starter-kit-antd.git
cd react-starter-kit-antd
yarn install && yarn start

Hey that's pretty clever! I integrated this into a boilerplate to test with and seems to work pretty well, have you ran into any stability issues/crashes during HMR?

Here's a demo for anyone interested
https://github.com/tim-soft/react-starter-kit-antd

git clone https://github.com/tim-soft/react-starter-kit-antd.git
cd react-starter-kit-antd
yarn install && yarn start
@Kruemelkatze

This comment has been minimized.

Show comment
Hide comment
@Kruemelkatze

Kruemelkatze Mar 30, 2018

Hey, thanks! Glad that some people are using this! :)

We (8 devs in our company) did not encounter any issues with HMR yet. It may take a bit longer if the variables are changed because the Ant styles are recompiled. But changing branding colors isn't anything that you do on a regular basis :)

Owner

Kruemelkatze commented Mar 30, 2018

Hey, thanks! Glad that some people are using this! :)

We (8 devs in our company) did not encounter any issues with HMR yet. It may take a bit longer if the variables are changed because the Ant styles are recompiled. But changing branding colors isn't anything that you do on a regular basis :)

@Hazantip

This comment has been minimized.

Show comment
Hide comment
@Hazantip

Hazantip Apr 12, 2018

Thank's a lot, this magic works good!

Thank's a lot, this magic works good!

@TuxujPes

This comment has been minimized.

Show comment
Hide comment
@TuxujPes

TuxujPes Jun 11, 2018

This way, antd styles will be loaded after your component's styles, right?
If so, there will be no possibility to overwrite some pesky !importants :(

TuxujPes commented Jun 11, 2018

This way, antd styles will be loaded after your component's styles, right?
If so, there will be no possibility to overwrite some pesky !importants :(

@Kruemelkatze

This comment has been minimized.

Show comment
Hide comment
@Kruemelkatze

Kruemelkatze Jun 21, 2018

We included our styles in this order and do not have any issues with overriding:

// App.jsx
import 'ant.less';
import 'main.scss'; // our app styles

Before we switched to this solution, we loaded the Ant styles using Ant's import-loader. With this we had the exact same problem you describe, so we used a (really dirty!) hack and reversed the css chunks generated by HtmlWebpackPlugin.

// webpack.config.js
plugins: [
    new HtmlWebpackPlugin({
        // ...
        chunksSortMode: function (a, b) {
            // Reverse files in css chunk
        }
    }
]

I did not post the whole code as we strongly discourage this hack. ;)

Owner

Kruemelkatze commented Jun 21, 2018

We included our styles in this order and do not have any issues with overriding:

// App.jsx
import 'ant.less';
import 'main.scss'; // our app styles

Before we switched to this solution, we loaded the Ant styles using Ant's import-loader. With this we had the exact same problem you describe, so we used a (really dirty!) hack and reversed the css chunks generated by HtmlWebpackPlugin.

// webpack.config.js
plugins: [
    new HtmlWebpackPlugin({
        // ...
        chunksSortMode: function (a, b) {
            // Reverse files in css chunk
        }
    }
]

I did not post the whole code as we strongly discourage this hack. ;)

@ZhangYiJiang

This comment has been minimized.

Show comment
Hide comment
@ZhangYiJiang

ZhangYiJiang Jul 3, 2018

How does this compare to using https://github.com/mediafreakch/less-plugin-sass2less instead? That seems to be less hacky and supports eg. mixins if you need to use them to define the SASS variables

How does this compare to using https://github.com/mediafreakch/less-plugin-sass2less instead? That seems to be less hacky and supports eg. mixins if you need to use them to define the SASS variables

@JabFury

This comment has been minimized.

Show comment
Hide comment
@JabFury

JabFury Jul 6, 2018

var content = require("!!../../../node_modules/_css-loader@0.28.11@css-loader/index.js!../../../node_modules/_sass-loader@7.0.3@sass-loader/lib/loader.js!./variables.scss");
^
Unrecognised input

When I try to npm run dev, my terminal show this message for me,I don't know how to solve this

JabFury commented Jul 6, 2018

var content = require("!!../../../node_modules/_css-loader@0.28.11@css-loader/index.js!../../../node_modules/_sass-loader@7.0.3@sass-loader/lib/loader.js!./variables.scss");
^
Unrecognised input

When I try to npm run dev, my terminal show this message for me,I don't know how to solve this

@atav32

This comment has been minimized.

Show comment
Hide comment
@atav32

atav32 Jul 17, 2018

@JabFury, looks like you might be missing the sass-loader?

Nvm, I got this error too. It's because my webpack config is the one that comes with create-react-app and I put the second Sass rule in the wrong place. I'm able to fix that bug if I make sure the rule is outside the oneOf rule.

  ...
  modules: {
    rules: [
      ...
      {
        oneOf: [
          // default loaders
          ...
        ]
      },
      {
        test: /\.scss$/,
        issuer: /\.less$/,
        use: {
          loader: require.resolve('./sassVarsToLess'),
        }
      }
    ]
  },
  ...

atav32 commented Jul 17, 2018

@JabFury, looks like you might be missing the sass-loader?

Nvm, I got this error too. It's because my webpack config is the one that comes with create-react-app and I put the second Sass rule in the wrong place. I'm able to fix that bug if I make sure the rule is outside the oneOf rule.

  ...
  modules: {
    rules: [
      ...
      {
        oneOf: [
          // default loaders
          ...
        ]
      },
      {
        test: /\.scss$/,
        issuer: /\.less$/,
        use: {
          loader: require.resolve('./sassVarsToLess'),
        }
      }
    ]
  },
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment