CSS

Parcel 包含对 CSS 的开箱即用支持。要添加 CSS 文件,请在 HTML 文件中使用 <link> 标签引用它

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

或从 JavaScript 文件导入它

import './index.css';

依赖项

#

CSS 资产可以包含通过 @import 语法引用的依赖项,以及通过 url() 函数引用的图像、字体等。

@import

#

@import at-规则可用于将另一个 CSS 文件内联到与包含文件相同的 CSS 包中。这意味着在运行时,不需要单独的网络请求来加载依赖项。

@import 'other.css';

引用的文件应相对于包含的 CSS 文件 相对。您也可以使用 绝对波浪号 指定符。要从 npm 导入 CSS 文件,请使用 npm: 方案

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

当启用 @parcel/resolver-glob 插件时,您也可以使用 glob 同时导入多个 CSS 文件。有关更多详细信息,请参阅 Glob 指定符

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

url()

#

url() 函数可用于引用文件,例如背景图像或字体。引用的文件将由 Parcel 处理,并且 URL 引用将被重写以指向输出文件名。

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

引用的文件应相对于包含的 CSS 文件 相对。您也可以使用 绝对波浪号 指定符。data-url: 方案也可用于将文件内联为数据 URL。有关更多详细信息,请参阅 包内联

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

注意:在 CSS 自定义属性中,只能使用 绝对路径,不能使用相对路径。这是因为自定义属性中的 url() 引用是从使用 var() 的位置解析的,而不是从定义自定义属性的位置解析的。这意味着自定义属性可能会解析为不同的 URL,具体取决于它在哪个文件中使用。为了解决这种歧义,在自定义属性中引用 URL 时,请使用绝对路径。

/src/index.css
body {
/* ❌ relative paths are not allowed in custom properties. */
--logo: url(images/logo.png);
/* ✅ use absolute paths instead. */
--logo: url(/src/images/logo.png);
}
/src/home/header.css
.logo {
background: var(--logo);
}

在上面的示例中,相对路径 images/logo.png 将解析为 /src/home/images/logo.png 而不是 /src/images/logo.png(正如您可能预期的那样),因为它是在 /src/home/header.css 中引用的。绝对路径 /src/images/logo.png 无论在哪个文件中使用 var(--logo),都会一致地解析。

CSS 模块

#

默认情况下,从 JavaScript 导入的 CSS 是全局的。如果两个 CSS 文件定义了相同的类名、id、自定义属性、@keyframes 等,它们可能会发生冲突并相互覆盖。为了解决这个问题,Parcel 支持 CSS 模块

CSS 模块将每个文件中定义的类视为唯一的。每个类名或标识符都会被重命名以包含一个唯一的哈希值,并且一个映射会被导出到 JavaScript 以便引用它们。

要使用 CSS 模块,请创建一个扩展名为 .module.css 的文件,并使用 命名空间导入 从 JavaScript 文件中导入它。然后,您可以将 CSS 文件中定义的每个类作为模块的导出进行访问。

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

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

.body 类将被重命名为一个唯一的值,以避免与其他 CSS 文件中的选择器冲突。

CSS 模块也适用于其他编译为 CSS 的语言,例如 SASS、Less 或 Stylus。使用相应的扩展名命名您的文件,例如 .module.scss.module.less.module.styl

摇树优化

#

使用 CSS 模块还有另一个好处,那就是使代码中对特定类名的依赖关系变得明确。这使得未使用的 CSS 类可以自动删除。

Example of tree shaking CSS modules

如您在上面的示例中看到的,只使用了 .button 类,因此未使用的 .cta 类已从编译后的 CSS 文件中删除。

这也适用于其他未使用的 CSS 规则,例如 @keyframes@counter-style,以及 CSS 自定义属性(当启用 dashedIdents 选项时)。

注意:摇树优化仅在您使用 命名空间命名 导入引用类时才有效。摇树优化不适用于 默认导入

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

应该替换为

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

本地 CSS 变量

#

默认情况下,类名、id 选择器以及 @keyframes@counter-style 以及 CSS 网格线和区域的名称都限定在它们定义的模块中。可以使用项目根目录 package.json 中的 dashedIdents 配置选项来启用对 CSS 变量和其他 <dashed-ident> 名称的限定。

package.json
{
"@parcel/transformer-css": {
"cssModules": {
"dashedIdents": true
}
}
}

启用后,CSS 变量将被重命名,以避免与其他文件中定义的变量名冲突。引用变量使用标准的 var() 语法,Parcel 将更新它以匹配本地限定的变量名。

您也可以使用 from 关键字引用其他文件中定义的变量

style.module.css
.button {
background: var(--accent-color from "./vars.module.css");
}
vars.module.css
:root {
--accent-color: hotpink;
}

可以使用 from global 语法引用全局变量,但是,它们目前必须在非 CSS 模块文件中定义。

style.module.css
@import "vars.css";

.button {
color: var(--color from global);
}
vars.css
:root {
--color: purple;
}

相同的语法也适用于使用 <dashed-ident> 语法的其他 CSS 值。例如,@font-palette-values 规则和 font-palette 属性使用 <dashed-ident> 语法来定义和引用自定义字体颜色调色板,并且将以与 CSS 变量相同的方式进行限定和引用。

自定义命名模式

#

默认情况下,Parcel 会将文件名的哈希值作为前缀添加到 CSS 文件中的每个类名和标识符。您可以使用项目根目录 package.json 中的 "pattern" 选项来配置此命名模式。它接受一个包含占位符的字符串,这些占位符将由 Parcel 填充,允许您添加自定义前缀或调整限定类的命名约定。

package.json
{
"@parcel/transformer-css": {
"cssModules": {
"pattern": "my-company-[name]-[hash]-[local]"
}
}
}

目前支持以下占位符

注意:由于浏览器会自动添加后缀,导致网格模板区域的线名以 -start-end 结尾,因此 CSS 网格线名可能会出现歧义。使用 CSS 网格时,您的 "pattern" 配置必须以 [local] 占位符结尾,以便这些引用能够正常工作。

grid.module.css
.grid {
grid-template-areas: "nav main";
}

.nav {
grid-column-start: nav-start;
}
package.json
{
"@parcel/transformer-css": {
"cssModules": {
// ❌ [local] must be at the end so that
// auto-generated grid line names work
"pattern": "[local]-[hash]"
// ✅ do this instead
"pattern": "[hash]-[local]"
}
}
}

全局启用 CSS 模块

#

默认情况下,CSS 模块仅对名称以 .module.css 结尾的文件启用。默认情况下,所有其他 CSS 文件都被视为全局 CSS。但是,可以通过在项目根目录 package.json 中配置 @parcel/transformer-css 来覆盖此行为,以便为所有源文件(即不在 node_modules 中的文件)启用 CSS 模块。

package.json
{
"@parcel/transformer-css": {
"cssModules": true
}
}

使用包含其他选项的配置对象时,请使用 "global" 选项。

{
"@parcel/transformer-css": {
"cssModules": {
"global": true,
// ...
}
}
}

注意:在 Parcel 的早期版本中,postcss-modules 用于实现 CSS 模块支持。全局启用 CSS 模块是在项目的 PostCSS 配置文件中完成的。如果您按上述方式启用 CSS 模块,则可以从 PostCSS 配置文件中删除此插件。

如果这是您使用的唯一 PostCSS 插件,则可以完全删除 PostCSS 配置文件。这可以显著提高构建性能。如果您没有使用任何 postcss-modules 配置选项,您可能会看到有关此问题的警告。

转译

#

Parcel 包含对转译现代 CSS 语法以支持旧版浏览器的开箱即用支持,包括供应商前缀和语法降低。此外,还支持 PostCSS 以启用自定义 CSS 转换。

浏览器目标

#

默认情况下,Parcel 不会对旧版浏览器执行任何 CSS 语法转译。这意味着如果您使用现代语法或不带供应商前缀编写代码,Parcel 将输出的就是这些代码。您可以使用 package.json 中的 browserslist 字段声明应用程序支持的浏览器。声明此字段后,Parcel 将相应地转译您的代码,以确保与支持的浏览器兼容。

package.json
{
"browserslist": "> 0.5%, last 2 versions, not dead"
}

有关如何配置此功能的更多详细信息,请参阅 目标 文档。

供应商前缀

#

根据您配置的浏览器目标,Parcel 会自动为许多 CSS 功能添加供应商前缀回退。例如,使用 image-set() 函数时,Parcel 还会输出回退 -webkit-image-set() 值,因为 Chrome 尚未支持未加前缀的值。

.logo {
background: image-set(url(logo.png) 2x, url(logo.png) 1x);
}

编译为

.logo {
background: -webkit-image-set(url(logo.png) 2x, url(logo.png) 1x);
background: image-set("logo.png" 2x, "logo.png");
}

此外,如果您的 CSS 源代码(或更可能是库)包含不必要的供应商前缀,Parcel CSS 会自动删除它们,以减小包大小。例如,在为现代浏览器编译时,transition 属性的前缀版本将被删除,因为所有浏览器都支持未加前缀的版本。

.button {
-webkit-transition: background 200ms;
-moz-transition: background 200ms;
transition: background 200ms;
}

变为

.button {
transition: background .2s;
}

语法降低

#

Parcel 会自动将许多现代 CSS 语法功能编译为更兼容的输出,这些输出在您的目标浏览器中受支持。

支持以下功能

草案语法

#

Parcel 还可以配置为编译一些尚未在任何浏览器中原生提供的草案规范。由于这些是草案,语法仍然可能发生变化,因此必须在项目中手动启用它们。

嵌套

#

The CSS 嵌套 草案规范允许样式规则进行嵌套,子规则的选择器以某种方式扩展父选择器。这在 SASS 等 CSS 预处理器中非常普遍,但有了这个规范,它最终将在浏览器中得到原生支持。Parcel 将此语法编译为今天所有浏览器都支持的非嵌套样式规则。

由于嵌套是草案,因此默认情况下不会启用它。要使用它,请通过在项目根目录的 package.json 文件中配置 @parcel/transformer-css 来启用它。

package.json
{
"@parcel/transformer-css": {
"drafts": {
"nesting": true
}
}
}

启用后,项目中的任何 CSS 文件都可以直接使用嵌套样式规则或 @nest at 规则。

直接嵌套的样式规则 必须以 & 嵌套选择器为前缀。这指示父选择器将在哪里被替换。例如

.foo {
color: blue;
& > .bar { color: red; }
}

等效于

.foo { color: blue; }
.foo > .bar { color: red; }

The @nest 规则 允许在父选择器被替换为开始位置以外的其他位置时进行嵌套。

.foo {
color: red;
@nest .parent & {
color: blue;
}
}

等效于

.foo { color: red; }
.parent .foo { color: blue; }

条件规则,例如 @media,也可以嵌套在样式规则中,而无需重复选择器。例如

.foo {
display: grid;

@media (orientation: landscape) {
grid-auto-flow: column;
}
}

等效于

.foo { display: grid; }

@media (orientation: landscape) {
.foo {
grid-auto-flow: column;
}
}

自定义媒体查询

#

自定义媒体查询 的支持包含在媒体查询级别 5 草案规范中。这允许您定义在 CSS 文件中的多个位置重复使用的媒体查询。Parcel CSS 将在启用此功能时提前执行此替换。

例如

@custom-media --modern (color), (hover);

@media (--modern) and (width > 1024px) {
.a { color: green; }
}

等效于

@media ((color) or (hover)) and (width > 1024px) {
.a { color: green; }
}

由于自定义媒体查询是草案,因此默认情况下不会启用它们。要使用它们,请通过在项目根目录的 package.json 文件中配置 @parcel/transformer-css 来启用 customMedia 功能。

package.json
{
"@parcel/transformer-css": {
"drafts": {
"customMedia": true
}
}
}

伪类替换

#

Parcel 支持将 :focus-visible 等 CSS 伪类替换为可以使用 JavaScript 应用的普通 CSS 类。这使得为旧版浏览器填充这些伪类成为可能。

伪类映射可以在项目根目录的 package.json 文件中配置

package.json
{
"@parcel/transformer-css": {
"pseudoClasses": {
"focusVisible": "focus-visible"
}
}
}

上面的配置将导致所有选择器中的 :focus-visible 伪类被替换为 .focus-visible 类。这使您能够使用 JavaScript polyfill,它将根据需要应用 .focus-visible 类。

以下伪类可以按上述方式配置

PostCSS

#

PostCSS 是一个使用插件转换 CSS 的工具。虽然 Parcel 支持许多常见 PostCSS 插件(例如 autoprefixerpostcss-preset-env)的等效功能,如上所述,PostCSS 对于更自定义的 CSS 转换(例如非标准语法添加)很有用。它也被流行的 CSS 框架(例如 Tailwind)使用。

您可以通过使用以下名称之一创建配置文件来在 Parcel 中使用 PostCSS:.postcssrc.postcssrc.json.postcssrc.js.postcssrc.mjs.postcssrc.cjspostcss.config.jspostcss.config.mjspostcss.config.cjs

首先,将您希望在应用程序中使用的 postcss 插件安装到您的应用程序中

yarn add tailwindcss --dev

然后,创建一个 .postcssrc。插件在 plugins 对象中作为键指定,选项使用对象值定义。如果插件没有选项,只需将其设置为 true 即可。

如果您的插件需要额外的配置,请也创建这些文件。例如,使用 Tailwind,您需要一个 tailwind.config.js

.postcssrc
{
"plugins": {
"tailwindcss": true
}
}
tailwind.config.js
module.exports = {
content: ["./src/*.{html,js}"],
theme: {
extend: {},
},
variants: {},
plugins: [],
};

默认插件

#

当在您的 package.json 中指定 browserslist 时,Parcel 会自动包含 autoprefixerpostcss-preset-env 的等效项。这些 在 Rust 中实现,并且比 PostCSS 快得多。如果这些是您项目中唯一需要的转换,那么您可能根本不需要 PostCSS。

如果您有一个现有项目,其中 PostCSS 配置仅包含上述插件,您可能可以完全删除它。如果您使用的是其他插件,您可以删除 autoprefixerpostcss-preset-env,同时只保留自定义插件。这可以显着提高构建性能,因为 Parcel 的内置转译器比 PostCSS 快得多。

有关 Parcel 的内置转译支持的更多详细信息,请参阅 上面

postcss-import

#

默认情况下,Parcel 会独立地使用 PostCSS 转换每个 CSS 文件。但是,一些 PostCSS 插件(例如 postcss-custom-properties)可能需要访问来自其他 @imported CSS 资产的声明。

在这些情况下,您可以使用 postcss-import 来一次性对整个捆绑包运行 PostCSS。 postcss-url 也应该用于确保在内联导入文件时 url() 引用被正确解析。

.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");
}

生产

#

在生产模式下,Parcel 包含优化以减小代码的文件大小。有关此工作原理的更多详细信息,请参阅 生产

缩小

#

在生产模式下,Parcel 会自动缩小您的代码以减小捆绑包的文件大小。默认情况下,Parcel 使用 lightningcss 执行 CSS 缩小。

注意:在之前的版本中,Parcel 使用 cssnano 进行缩小。如果您的项目包含 cssnano 配置文件(例如 .cssnanorccssnano.config.json),您可能会看到升级 Parcel 后不再应用它的警告。

在大多数情况下,您可以简单地删除 cssnano 配置文件并让 Parcel 处理缩小。但是,如果您确实依赖于此配置中的某些设置,并且希望继续使用 cssnano 而不是 lightningcss 进行缩小,您可以配置 Parcel 使用 @parcel/optimizer-cssnano 代替。

.parcelrc
{
"extends": "@parcel/config-default",
"optimizers": {
"*.css": ["@parcel/optimizer-cssnano"]
}
}