88

Some third-party modules I'm using have their own CSS files. I'd like to include them in my app's one, single CSS file, which is processed by Webpack. How can CSS files under "node_modules" be imported into my CSS file?

For example, I'm using the third-party react-select module, but I can't import its CSS file from node_modules:

@import 'react-select/dist/react-datetime.css';

The relevant loader in webpack.config.js:

  {
    test: /\.css$/,
    use: ExtractTextPlugin.extract({
      use: [
        {
          loader: 'css-loader',
          options: {
            url: false
          }
        }
      ]
    })
  }
1
  • I,m interested in using @import the same way, but with Vite (not webpack) Commented Nov 23, 2023 at 19:25

5 Answers 5

147

You can import files relative to your project's root (resolving node_modules/ from the root folder) by prefixing with a tilde ~:

@import '~react-select/dist/react-datetime.css';

This is a poorly documented Webpack (a redundant phrase) convention, see https://github.com/webpack-contrib/css-loader/issues/12#issuecomment-41940311 and What does a `~` tilde in a CSS `url()` do?

Sign up to request clarification or add additional context in comments.

2 Comments

Note that it is now documented: webpack.js.org/loaders/css-loader/#url webpack.js.org/loaders/css-loader/#import "To import assets from a node_modules path (include resolve.modules) and for alias, prefix it with a ~" Also, note that it is not a core webpack feature but a feature of css-loader.
I had to remove the .css extension for it to work for some reason
4

I had a similar issue today. After all, all I had to do was to configure resolve in my webpack config file. I hope this will help somebody.

Webpack version I used:

"webpack": "^4.37.0",

In a webpack config file, the following should be configured:

module.exports = {
  resolve: {
    extensions: ['.json', '.js', '.jsx'],
    modules: ['node_modules'],
  },

or

module.exports = {
  resolve: {
    alias: {
      'some-library': path.resolve(__dirname, './node_modules/some-library'),
    }
  },

In a css file, we can access a library by a relative path from node_modules:

@import '~some-library/src/some-css-file';

1 Comment

This worked for me, but the @import statement needed to be @import 'node_modules/lib-name/file-name';
2

If you are using too many things from one node_modules folder you can also create an alias by passing this following option

options: {
    url: false,
    includePaths: [
        // this one for using node_modules as a base folder
        path.resolve('node_modules'),
        // this one for using sass as the base folder
        path.resolve('node_modules/flag-icon-css/sass')
    ]
}

After the configuration, you can import as you were trying in your question.

1 Comment

this is not recommended because node_modules usually too much big, this makes the searching process too much slow, at least make it the latest search path\
1

simply, prefix ~ to be replaced with the path of node_modules at compile time.

@import '~package-name/css-file';

however, this is a webpack feature (not an Angular feature).

since Angular projects now use esbuild, this feature will no longer work in newer Angular versions

for EsBuild use:

@import 'package-name/css-file.css';

Comments

0

I use Webpack 5. I also have been having a problem of not being able to import an external .css file from an external library. I tried adding resolve:[...] property to my webpack.config.js file, among other tryings, but all that was to no avail: webpack did not inject styles. Then I discovered a following hack: instead of importing .css in the usual import "external-lib/style.css" manner (which didn't help me in my case), I did a named import as follows:

import necessaryStyle from "external-lib/style.css";
const ReactComponent = () => {
    console.log("necessity logging: ", necessaryStyle);
...}

The console.log statement will print undefined but the trick worked in my case. The external styles were injected into the <style><style/> tags of my .html document.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.