CSS

Parcel includes support for CSS out of the box. To add a CSS file, either reference it with a <link> tag in an HTML file:

<link rel="stylesheet" href="index.css" />

or import it from a JavaScript file:

import './index.css';

Dependencies

#

CSS assets can contain dependencies referenced by @import syntax, as well as references to images, fonts, etc. via the url() function.

@import

#

The @import at-rule can be used to inline another CSS file into the same CSS bundle as the containing file. This means that at runtime a separate network request will not be needed to load the dependency.

@import 'other.css';

Referenced files should be relative to the containing CSS file. You can also use absolute and tilde specifiers. To import a CSS file from npm, use the npm: scheme.

@import 'npm:bootstrap/bootstrap.css';

When the @parcel/resolver-glob plugin is enabled, you can also use globs to import multiple CSS files at once. See Glob specifiers for more details.

@import "./components/*.css";

url()

#

The url() function can be used to reference a file, for example a background image or font. The referenced file will be processed by Parcel, and the URL reference will be rewritten to point to the output filename.

body {
background: url('images/background.png');
}

Referenced files should be relative to the containing CSS file. You can also use absolute and tilde specifiers. The data-url: scheme can also be used to inline a file as a data URL. See Bundle inlining for more details.

.logo {
background: url('data-url:./logo.png');
}

CSS modules

#

By default, CSS imported from JavaScript is global. If two CSS files define the same class names, they will potentially clash and overwrite each other. To solve this, Parcel supports CSS modules.

CSS modules treat the classes defined in each file as unique. Each class name is renamed to include a unique hash, and a mapping is exported to JavaScript to allow referencing these renamed class names.

To use CSS modules, create a file with the .module.css extension, and import it from a JavaScript file with a namespace import. Then, you can access each of the classes defined in the CSS file as an export from the module.

import * as classes from './styles.module.css';

document.body.className = classes.body;
.body {
background: skyblue;
}

The .body class will be renamed to something unique to avoid selector clashes with other CSS files.

CSS modules also work with other languages that compile to CSS, such as SASS, Less, or Stylus. Name your file using the corresponding file extension, such as .module.scss, .module.less, or .module.styl.

Tree shaking

#

Using CSS modules also has the benefit of making dependencies on specific class names explicit in your code. This enables unused CSS classes to be automatically removed.

Example of tree shaking CSS modules

As you can see in the above example, only the .button class is used, so the unused .cta class is removed from the compiled CSS file.

Note: Tree shaking only works when you reference classes using either a namespace or named import. Tree shaking does not work with default imports.

import styles from './styles.module.css';

should be replaced with:

import * as styles from './styles.module.css';

Enabling CSS modules globally

#

By default, CSS modules are only enabled for files ending with .module.css. All other CSS files are treated as global CSS by default. However, this can be overridden using a PostCSS config. This also allows customizing the options of postcss-modules.

.postcssrc:
{
"modules": true,
"plugins": {
"postcss-modules": {
"generateScopedName": "_[name]__[local]"
}
}
}

PostCSS

#

PostCSS is a tool for transforming CSS with plugins, like autoprefixer, Preset Env, and many others. You can configure PostCSS with Parcel by creating a configuration file using one of these names: .postcssrc, .postcssrc.json, .postcssrc.js, or postcss.config.js.

Install plugins in your app:

yarn add autoprefixer --dev

Then, create a .postcssrc:

.postcssrc:
{
"plugins": {
"autoprefixer": {
"grid": true
}
}
}

Plugins are specified in the plugins object as keys, and options are defined using object values. If there are no options for a plugin, just set it to true instead.

Target browsers for Autoprefixer, cssnext and other tools can be specified in a Browserslist.

postcss-import

#

By default, Parcel transforms each CSS file with PostCSS independently. However, some PostCSS plugins (e.g. postcss-custom-properties) potentially need to access declarations from other @imported CSS assets.

In these cases, you can use postcss-import to run PostCSS over the whole bundle at once instead. postcss-url should also be used to ensure url() references are resolved correctly when imported files are inlined.

.postcssrc:
{
"plugins": {
"postcss-import": true,
"postcss-url": true,
"postcss-custom-properties": true
}
}
app.css:
@import "./config/index.css";

html {
background-color: var(--varColor);
}

.icon {
width: 50px;
height: 50px;
background-image: var(--varIcon);
}
config/index.css:
:root {
--varColor: red;
--varIcon: url("../icon.svg");
}

Production

#

In production mode, Parcel includes optimizations to reduce the file size of your code. See Production for more details about how this works.

Minification

#

In production mode, Parcel automatically minifies your code to reduce the file sizes of your bundles. By default, Parcel uses cssnano to perform CSS minification. To configure cssnano, you can create a .cssnanorc or cssnano.config.json file in your project root directory.

.cssnanorc:
{
"preset": [
"default",
{
"calc": false,
"discardComments": {
"removeAll": true
}
}
]
}

Note: cssnano.config.js is also supported for JavaScript-based configuration, but should be avoided when possible because it reduces the effectiveness of Parcel's caching. Use a JSON based configuration format (e.g. cssnano.config.json) instead.