> ## Documentation Index
> Fetch the complete documentation index at: https://bun.ll1025.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# CSS

> Bun 的打包器内置了对 CSS 的支持，包含现代特性

Bun 的打包器内置了对 CSS 的支持，具有以下特性：

* 转译现代/未来特性以在所有浏览器上工作（包括供应商前缀）
* 压缩
* CSS Modules
* Tailwind（通过原生打包器插件）

## 转译

转译和供应商前缀默认启用，因此你可以使用现代和未来的 CSS 特性，而无需担心浏览器兼容性。

Bun 的 CSS 解析器和打包器是 LightningCSS 的直接移植，采用受 esbuild 启发的打包方式。转译器将现代 CSS 语法转换为向后兼容的等效形式，可在所有浏览器中工作。

<Note>感谢 LightningCSS 和 esbuild 的作者们的出色工作。</Note>

## 浏览器兼容性

默认情况下，Bun 的 CSS 打包器针对以下浏览器：

* ES2020
* Edge 88+
* Firefox 78+
* Chrome 87+
* Safari 14+

## 语法降级

### 嵌套

使用 CSS 嵌套，你可以直接在父级块内部编写子级样式，而无需在 CSS 文件中重复父级选择器。

```scss title="styles.css" icon="file-code" theme={null}
/* 使用嵌套 */
.card {
  background: white;
  border-radius: 4px;

  .title {
    font-size: 1.2rem;
    font-weight: bold;
  }

  .content {
    padding: 1rem;
  }
}
```

Bun 的 CSS 打包器自动将此嵌套语法转换为在所有浏览器中都能工作的传统扁平 CSS：

```css title="styles.css" icon="file-code" theme={null}
/* 编译后的输出 */
.card {
  background: white;
  border-radius: 4px;
}

.card .title {
  font-size: 1.2rem;
  font-weight: bold;
}

.card .content {
  padding: 1rem;
}
```

你也可以在选择器内部嵌套媒体查询和其他 at 规则：

```scss title="styles.css" icon="file-code" theme={null}
.responsive-element {
  display: block;

  @media (min-width: 768px) {
    display: flex;
  }
}
```

编译为：

```css title="styles.css" icon="file-code" theme={null}
.responsive-element {
  display: block;
}

@media (min-width: 768px) {
  .responsive-element {
    display: flex;
  }
}
```

### Color-mix 函数

`color-mix()` 函数在选定的色彩空间中按给定比例混合两种颜色。无需自己计算结果即可创建颜色变体。

```scss title="styles.css" icon="file-code" theme={null}
.button {
  /* 在 RGB 色彩空间中以 30/70 比例混合蓝色和红色 */
  background-color: color-mix(in srgb, blue 30%, red);

  /* 为悬停状态创建更亮的变体 */
  &:hover {
    background-color: color-mix(in srgb, blue 30%, red, white 20%);
  }
}
```

当所有颜色值都已知（不是 CSS 变量）时，Bun 的 CSS 打包器在构建时评估这些颜色混合，生成在所有浏览器中工作的静态颜色值：

```css title="styles.css" icon="file-code" theme={null}
.button {
  /* 计算为精确的结果颜色 */
  background-color: #b31a1a;
}

.button:hover {
  background-color: #c54747;
}
```

### 相对颜色

相对颜色语法修改现有颜色的各个分量。调整亮度、饱和度或单个通道属性，而无需重新计算整个颜色。

```css title="styles.css" icon="file-code" theme={null}
.theme-color {
  /* 从基础颜色开始，亮度增加 15% */
  --accent: lch(from purple calc(l + 15%) c h);

  /* 获取品牌蓝色并制作去饱和版本 */
  --subtle-blue: oklch(from var(--brand-blue) l calc(c * 0.8) h);
}
```

当不使用 CSS 变量时，Bun 的 CSS 打包器在构建时计算这些相对颜色修改，生成静态颜色值以确保浏览器兼容性：

```css theme={null}
.theme-color {
  --accent: lch(69.32% 58.34 328.37);
  --subtle-blue: oklch(60.92% 0.112 240.01);
}
```

用于主题生成、无障碍颜色变体或从基础颜色派生的颜色比例，而不是硬编码每个值。

### LAB 颜色

现代 CSS 支持感知均匀的色彩空间 LAB、LCH、OKLAB 和 OKLCH，它们可以表示超出标准 RGB 色域的颜色。

```css title="styles.css" icon="file-code" theme={null}
.vibrant-element {
  /* 超出 sRGB 色域边界的鲜艳红色 */
  color: lab(55% 78 35);

  /* 使用感知色彩空间的平滑渐变 */
  background: linear-gradient(to right, oklch(65% 0.25 10deg), oklch(65% 0.25 250deg));
}
```

Bun 的 CSS 打包器将这些颜色格式转换为不支持的浏览器的向后兼容替代方案：

```css title="styles.css" icon="file-code" theme={null}
.vibrant-element {
  /* 回退到最接近的 RGB 近似值 */
  color: #ff0f52;
  /* 对于有更宽色域支持的浏览器使用 P3 回退 */
  color: color(display-p3 1 0.12 0.37);
  /* 原始值保留给支持的浏览器 */
  color: lab(55% 78 35);

  background: linear-gradient(to right, #cd4e15, #3887ab);
  background: linear-gradient(to right, oklch(65% 0.25 10deg), oklch(65% 0.25 250deg));
}
```

### Color 函数

`color()` 函数在超出传统 RGB 范围的预定义色彩空间中指定颜色，让你访问更宽的色域。

```css title="styles.css" icon="file-code" theme={null}
.vivid-element {
  /* 使用 Display P3 色彩空间获得更宽色域的颜色 */
  color: color(display-p3 1 0.1 0.3);

  /* 使用 A98 RGB 色彩空间 */
  background-color: color(a98-rgb 0.44 0.5 0.37);
}
```

对于不支持这些色彩空间的浏览器，Bun 的 CSS 打包器添加 RGB 回退：

```css title="styles.css" icon="file-code" theme={null}
.vivid-element {
  /* 首先使用 RGB 回退以获得最大兼容性 */
  color: #fa1a4c;
  /* 保留原始值给支持的浏览器 */
  color: color(display-p3 1 0.1 0.3);

  background-color: #6a805d;
  background-color: color(a98-rgb 0.44 0.5 0.37);
}
```

### HWB 颜色

HWB（色调、白度、黑度）颜色模型根据纯色调混合了多少白色或黑色来表达颜色。这使得创建色调和明暗比使用 RGB 或 HSL 值更直接。

```css title="styles.css" icon="file-code" theme={null}
.easy-theming {
  /* 纯青色，未添加白色或黑色 */
  --primary: hwb(180 0% 0%);

  /* 相同的色调，但添加了 20% 白色（色调） */
  --primary-light: hwb(180 20% 0%);

  /* 相同的色调，但添加了 30% 黑色（阴影） */
  --primary-dark: hwb(180 0% 30%);

  /* 同时添加白色和黑色的柔和版本 */
  --primary-muted: hwb(180 30% 20%);
}
```

Bun 的 CSS 打包器将 HWB 颜色转换为 RGB 以确保与所有浏览器兼容：

```css title="styles.css" icon="file-code" theme={null}
.easy-theming {
  --primary: #00ffff;
  --primary-light: #33ffff;
  --primary-dark: #00b3b3;
  --primary-muted: #339999;
}
```

### 颜色表示法

现代 CSS 支持空格分隔的 RGB 和 HSL 值（无逗号）和带 alpha 通道的十六进制颜色。

```css title="styles.css" icon="file-code" theme={null}
.modern-styling {
  /* 空格分隔的 RGB 表示法（无逗号） */
  color: rgb(50 100 200);

  /* 带 alpha 的空格分隔 RGB */
  border-color: rgba(100 50 200 / 75%);

  /* 带 alpha 通道的十六进制（8 位） */
  background-color: #00aaff80;

  /* 简化表示法的 HSL */
  box-shadow: 0 5px 10px hsl(200 50% 30% / 40%);
}
```

Bun 的 CSS 打包器将这些格式转换为旧浏览器的格式：

```css title="styles.css" icon="file-code" theme={null}
.modern-styling {
  /* 转换为旧浏览器的逗号格式 */
  color: rgb(50, 100, 200);

  /* Alpha 通道适当处理 */
  border-color: rgba(100, 50, 200, 0.75);

  /* 十六进制+alpha 在需要时转换为 rgba */
  background-color: rgba(0, 170, 255, 0.5);

  box-shadow: 0 5px 10px rgba(38, 115, 153, 0.4);
}
```

### light-dark() 颜色函数

`light-dark()` 函数接受两种颜色，根据当前配色方案应用其中一种，因此无需媒体查询即可使样式尊重用户的系统偏好。

```css title="styles.css" icon="file-code" theme={null}
:root {
  /* 定义配色方案支持 */
  color-scheme: light dark;
}

.themed-component {
  /* 根据系统偏好自动选择正确的颜色 */
  background-color: light-dark(#ffffff, #121212);
  color: light-dark(#333333, #eeeeee);
  border-color: light-dark(#dddddd, #555555);
}

/* 需要时覆盖系统偏好 */
.light-theme {
  color-scheme: light;
}

.dark-theme {
  color-scheme: dark;
}
```

对于不支持 `light-dark()` 的浏览器，Bun 的 CSS 打包器将其转换为带有回退的 CSS 变量：

```css title="styles.css" icon="file-code" theme={null}
:root {
  --buncss-light: initial;
  --buncss-dark: ;
  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root {
    --buncss-light: ;
    --buncss-dark: initial;
  }
}

.light-theme {
  --buncss-light: initial;
  --buncss-dark: ;
  color-scheme: light;
}

.dark-theme {
  --buncss-light: ;
  --buncss-dark: initial;
  color-scheme: dark;
}

.themed-component {
  background-color: var(--buncss-light, #ffffff) var(--buncss-dark, #121212);
  color: var(--buncss-light, #333333) var(--buncss-dark, #eeeeee);
  border-color: var(--buncss-light, #dddddd) var(--buncss-dark, #555555);
}
```

### 逻辑属性

CSS 逻辑属性根据文档的书写模式和文本方向定义布局、间距和大小，而不是物理屏幕方向，因此布局可以适应不同的书写系统。

```css title="styles.css" icon="file-code" theme={null}
.multilingual-component {
  /* 适应书写方向的边距 */
  margin-inline-start: 1rem;

  /* 无论文本方向如何都有意义的内边距 */
  padding-block: 1rem 2rem;

  /* 顶部起始角的边框半径 */
  border-start-start-radius: 4px;

  /* 尊重书写模式的大小 */
  inline-size: 80%;
  block-size: auto;
}
```

对于不完全支持逻辑属性的浏览器，Bun 的 CSS 打包器为每种文本方向将它们编译为物理属性：

```css title="styles.css" icon="file-code" theme={null}
/* 对于从左到右的语言 */
.multilingual-component:dir(ltr) {
  margin-left: 1rem;
  padding-top: 1rem;
  padding-bottom: 2rem;
  border-top-left-radius: 4px;
  width: 80%;
  height: auto;
}

/* 对于从右到左的语言 */
.multilingual-component:dir(rtl) {
  margin-right: 1rem;
  padding-top: 1rem;
  padding-bottom: 2rem;
  border-top-right-radius: 4px;
  width: 80%;
  height: auto;
}
```

如果不支持 `:dir()` 选择器，Bun 会生成额外的回退。

### :dir() 选择器

`:dir()` 伪类根据元素的文本方向（RTL 或 LTR）来设置样式，由文档或显式的 direction 属性决定。无需 JavaScript 编写方向感知的样式。

```css title="styles.css" icon="file-code" theme={null}
/* 根据文本方向应用不同样式 */
.nav-arrow:dir(ltr) {
  transform: rotate(0deg);
}

.nav-arrow:dir(rtl) {
  transform: rotate(180deg);
}

/* 根据文本流向定位元素 */
.sidebar:dir(ltr) {
  border-right: 1px solid #ddd;
}

.sidebar:dir(rtl) {
  border-left: 1px solid #ddd;
}
```

对于不支持 `:dir()` 选择器的浏览器，Bun 的 CSS 打包器将其转换为更广泛支持的 `:lang()` 选择器，并带有适当的语言映射：

```css title="styles.css" icon="file-code" theme={null}
/* 转换为使用基于语言的选择器作为回退 */
.nav-arrow:lang(en, fr, de, es, it, pt, nl) {
  transform: rotate(0deg);
}

.nav-arrow:lang(ar, he, fa, ur) {
  transform: rotate(180deg);
}

.sidebar:lang(en, fr, de, es, it, pt, nl) {
  border-right: 1px solid #ddd;
}

.sidebar:lang(ar, he, fa, ur) {
  border-left: 1px solid #ddd;
}
```

如果不支持 `:lang()` 的多个参数，Bun 会生成进一步的回退。

### :lang() 选择器

`:lang()` 伪类根据元素的语言来选择目标。要为相关语言分组规则，将多个语言代码传递给单个 `:lang()`。

```css title="styles.css" icon="file-code" theme={null}
/* 针对 CJK 语言的排版调整 */
:lang(zh, ja, ko) {
  line-height: 1.8;
  font-size: 1.05em;
}

/* 按语言组划分不同的引用样式 */
blockquote:lang(fr, it, es, pt) {
  font-style: italic;
}

blockquote:lang(de, nl, da, sv) {
  font-weight: 500;
}
```

对于不支持 `:lang()` 选择器中多个参数的浏览器，Bun 的 CSS 打包器将此语法转换为 `:is()` 选择器，行为相同：

```css title="styles.css" icon="file-code" theme={null}
/* 使用 :is() 对多种语言进行分组以获得更好的浏览器支持 */
:is(:lang(zh), :lang(ja), :lang(ko)) {
  line-height: 1.8;
  font-size: 1.05em;
}

blockquote:is(:lang(fr), :lang(it), :lang(es), :lang(pt)) {
  font-style: italic;
}

blockquote:is(:lang(de), :lang(nl), :lang(da), :lang(sv)) {
  font-weight: 500;
}
```

如果需要，Bun 也可以为 `:is()` 生成额外的回退。

### :is() 选择器

`:is()` 伪类函数（原名 `:matches()`）接受一个选择器列表，如果列表中有任何选择器匹配则匹配。

```css title="styles.css" icon="file-code" theme={null}
/* 不用分别编写这些 */
/* 
.article h1,
.article h2,
.article h3 {
  margin-top: 1.5em;
}
*/

/* 你可以这样写 */
.article :is(h1, h2, h3) {
  margin-top: 1.5em;
}

/* 带多个分组的复杂示例 */
:is(header, main, footer) :is(h1, h2, .title) {
  font-family: "Heading Font", sans-serif;
}
```

对于不支持 `:is()` 的浏览器，Bun 的 CSS 打包器使用带供应商前缀的替代方案提供回退：

```css theme={null}
/* 使用 -webkit-any 回退 */
.article :-webkit-any(h1, h2, h3) {
  margin-top: 1.5em;
}

/* 使用 -moz-any 回退 */
.article :-moz-any(h1, h2, h3) {
  margin-top: 1.5em;
}

/* 为现代浏览器保留原始值 */
.article :is(h1, h2, h3) {
  margin-top: 1.5em;
}

/* 带回退的复杂示例 */
:-webkit-any(header, main, footer) :-webkit-any(h1, h2, .title) {
  font-family: "Heading Font", sans-serif;
}

:-moz-any(header, main, footer) :-moz-any(h1, h2, .title) {
  font-family: "Heading Font", sans-serif;
}

:is(header, main, footer) :is(h1, h2, .title) {
  font-family: "Heading Font", sans-serif;
}
```

<Warning>
  与标准化的 `:is()` 选择器相比，带供应商前缀的版本有局限性，特别是在复杂选择器中。Bun 仅在前缀版本能正确工作时使用它们。
</Warning>

### :not() 选择器

`:not()` 伪类排除匹配某个选择器的元素。现代版本接受多个参数，用一个 `:not()` 排除多种模式。

```css title="styles.css" icon="file-code" theme={null}
/* 选择所有除了主要和次要变体之外的按钮 */
button:not(.primary, .secondary) {
  background-color: #f5f5f5;
  border: 1px solid #ddd;
}

/* 将样式应用于所有标题，除了侧边栏或页脚内的 */
h2:not(.sidebar *, footer *) {
  margin-top: 2em;
}
```

对于不支持 `:not()` 中多个参数的浏览器，Bun 的 CSS 打包器将此语法转换为行为相同的更兼容形式：

```css title="styles.css" icon="file-code" theme={null}
/* 转换为使用 :not 配合 :is() 以保持兼容性 */
button:not(:is(.primary, .secondary)) {
  background-color: #f5f5f5;
  border: 1px solid #ddd;
}

h2:not(:is(.sidebar *, footer *)) {
  margin-top: 2em;
}
```

如果 `:is()` 不受支持，Bun 可以生成进一步的回退：

```css title="styles.css" icon="file-code" theme={null}
/* 为最大兼容性提供更多回退 */
button:not(:-webkit-any(.primary, .secondary)) {
  background-color: #f5f5f5;
  border: 1px solid #ddd;
}

button:not(:-moz-any(.primary, .secondary)) {
  background-color: #f5f5f5;
  border: 1px solid #ddd;
}

button:not(:is(.primary, .secondary)) {
  background-color: #f5f5f5;
  border: 1px solid #ddd;
}
```

转换后的选择器保持原始的特异性和行为。

### 数学函数

CSS 包含标准数学函数（`round()`、`mod()`、`rem()`、`abs()`、`sign()`）、三角函数（`sin()`、`cos()`、`tan()`、`asin()`、`acos()`、`atan()`、`atan2()`）和指数函数（`pow()`、`sqrt()`、`exp()`、`log()`、`hypot()`）。

```css title="styles.css" icon="file-code" theme={null}
.dynamic-sizing {
  /* 在最小值和最大值之间钳制一个值 */
  width: clamp(200px, 50%, 800px);

  /* 舍入到最近的倍数 */
  padding: round(14.8px, 5px);

  /* 用于动画或布局的三角函数 */
  transform: rotate(calc(sin(45deg) * 50deg));

  /* 带多个函数的复杂数学 */
  --scale-factor: pow(1.25, 3);
  font-size: calc(16px * var(--scale-factor));
}
```

当所有值都是已知常量（不是变量）时，Bun 的 CSS 打包器在构建时评估这些表达式：

```css title="styles.css" icon="file-code" theme={null}
.dynamic-sizing {
  width: clamp(200px, 50%, 800px);
  padding: 15px;
  transform: rotate(35.36deg);
  --scale-factor: 1.953125;
  font-size: calc(16px * var(--scale-factor));
}
```

### 媒体查询范围

媒体查询范围语法使用比较运算符（`<`、`>`、`<=`、`>=`）表达断点，而不是更冗长的 `min-` 和 `max-` 前缀。

```css title="styles.css" icon="file-code" theme={null}
/* 使用比较运算符的现代语法 */
@media (width >= 768px) {
  .container {
    max-width: 720px;
  }
}

/* 使用 <= 和 >= 的包含范围 */
@media (768px <= width <= 1199px) {
  .sidebar {
    display: flex;
  }
}

/* 使用 < 和 > 的排除范围 */
@media (width > 320px) and (width < 768px) {
  .mobile-only {
    display: block;
  }
}
```

Bun 的 CSS 打包器将范围查询转换为传统的媒体查询语法，以确保与所有浏览器兼容：

```css title="styles.css" icon="file-code" theme={null}
/* 转换为传统的 min/max 语法 */
@media (min-width: 768px) {
  .container {
    max-width: 720px;
  }
}

@media (min-width: 768px) and (max-width: 1199px) {
  .sidebar {
    display: flex;
  }
}

@media (min-width: 321px) and (max-width: 767px) {
  .mobile-only {
    display: block;
  }
}
```

### 简写属性

CSS 引入了一些组合多个长手属性的简写属性。

```css title="styles.css" icon="file-code" theme={null}
/* 对齐简写 */
.flex-container {
  /* align-items 和 justify-items 的简写 */
  place-items: center start;

  /* align-content 和 justify-content 的简写 */
  place-content: space-between center;
}

.grid-item {
  /* align-self 和 justify-self 的简写 */
  place-self: end center;
}

/* 双值 overflow */
.content-box {
  /* 第一个值水平，第二个值垂直 */
  overflow: hidden auto;
}

/* 增强的 text-decoration */
.fancy-link {
  /* 组合多个文本装饰属性 */
  text-decoration: underline dotted blue 2px;
}

/* 双值 display 语法 */
.component {
  /* 外部显示类型 + 内部显示类型 */
  display: inline flex;
}
```

对于不支持这些简写的浏览器，Bun 将它们转换为组成的长手属性：

```css title="styles.css" icon="file-code" theme={null}
.flex-container {
  /* 展开的对齐属性 */
  align-items: center;
  justify-items: start;

  align-content: space-between;
  justify-content: center;
}

.grid-item {
  align-self: end;
  justify-self: center;
}

.content-box {
  /* 单独的 overflow 属性 */
  overflow-x: hidden;
  overflow-y: auto;
}

.fancy-link {
  /* 单独的文本装饰属性 */
  text-decoration-line: underline;
  text-decoration-style: dotted;
  text-decoration-color: blue;
  text-decoration-thickness: 2px;
}

.component {
  /* 单值 display */
  display: inline-flex;
}
```

### 双位置渐变

双位置渐变语法在同一颜色的两个相邻位置指定它，以创建硬颜色停止：尖锐的过渡而不是平滑的渐变。用于条纹、色带和其他多色设计。

```css title="styles.css" icon="file-code" theme={null}
.striped-background {
  /* 在 30%-40% 处创建从绿色到红色的尖锐过渡 */
  background: linear-gradient(
    to right,
    yellow 0%,
    green 20%,
    green 30%,
    red 30%,
    /* 双位置创建硬停止 */ red 70%,
    blue 70%,
    blue 100%
  );
}

.progress-bar {
  /* 创建不同的颜色段落 */
  background: linear-gradient(
    to right,
    #4caf50 0% 25%,
    /* 绿色从 0% 到 25% */ #ffc107 25% 50%,
    /* 黄色从 25% 到 50% */ #2196f3 50% 75%,
    /* 蓝色从 50% 到 75% */ #9c27b0 75% 100% /* 紫色从 75% 到 100% */
  );
}
```

对于不支持此语法的浏览器，Bun 的 CSS 打包器通过复制颜色停止将其转换为传统格式：

```css title="styles.css" icon="file-code" theme={null}
.striped-background {
  background: linear-gradient(
    to right,
    yellow 0%,
    green 20%,
    green 30%,
    red 30%,
    /* 分成两个颜色停止 */ red 70%,
    blue 70%,
    blue 100%
  );
}

.progress-bar {
  background: linear-gradient(
    to right,
    #4caf50 0%,
    #4caf50 25%,
    /* 绿色段的两个停止 */ #ffc107 25%,
    #ffc107 50%,
    /* 黄色段的两个停止 */ #2196f3 50%,
    #2196f3 75%,
    /* 蓝色段的两个停止 */ #9c27b0 75%,
    #9c27b0 100% /* 紫色段的两个停止 */
  );
}
```

### system-ui 字体

`system-ui` 通用字体系列使用设备的原生 UI 字体。

```css title="styles.css" icon="file-code" theme={null}
.native-interface {
  /* 使用系统的默认 UI 字体 */
  font-family: system-ui;
}

.fallback-aware {
  /* 带显式回退的系统 UI 字体 */
  font-family: system-ui, sans-serif;
}
```

对于不支持 `system-ui` 的浏览器，Bun 的 CSS 打包器将其扩展为跨平台字体栈：

```css title="styles.css" icon="file-code" theme={null}
.native-interface {
  /* 扩展以支持所有主要平台 */
  font-family:
    system-ui,
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Noto Sans",
    Ubuntu,
    Cantarell,
    "Helvetica Neue";
}

.fallback-aware {
  /* 在扩展的字体栈之后保留原始回退 */
  font-family:
    system-ui,
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Noto Sans",
    Ubuntu,
    Cantarell,
    "Helvetica Neue",
    sans-serif;
}
```

扩展的字体栈包括 macOS/iOS、Windows、Android 和 Linux 的系统字体，以及旧浏览器的回退。

## CSS Modules

Bun 的打包器也支持 CSS 模块，具有以下功能：

* 无需配置即可检测 CSS 模块文件（`.module.css`）
* 组合（`composes` 属性）
* 将 CSS 模块导入到 JSX/TSX 中
* 对 CSS 模块的无效用法发出警告/错误

CSS 模块是一种 CSS 文件（带有 `.module.css` 扩展名），其中所有类名和动画都限定在文件范围内。这有助于避免类名冲突，因为默认情况下 CSS 声明是全局范围的。

Bun 的打包器将局部范围的类名转换为唯一标识符。

### 开始使用

创建带有 `.module.css` 扩展名的 CSS 文件：

```css title="styles.module.css" icon="file-code" theme={null}
.button {
  color: red;
}
```

```css title="other-styles.module.css" icon="file-code" theme={null}
.button {
  color: blue;
}
```

然后你可以导入这个文件，例如导入到 TSX 文件中：

```tsx title="app.tsx" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
import styles from "./styles.module.css";
import otherStyles from "./other-styles.module.css";

export default function App() {
  return (
    <>
      <button className={styles.button}>红色按钮！</button>
      <button className={otherStyles.button}>蓝色按钮！</button>
    </>
  );
}
```

导入 CSS 模块会为你提供一个对象，将每个类名映射到其唯一标识符：

```ts title="app.tsx" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
import styles from "./styles.module.css";
import otherStyles from "./other-styles.module.css";

console.log(styles);
console.log(otherStyles);
```

输出：

```ts title="app.tsx" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
{
  button: "button_123";
}

{
  button: "button_456";
}
```

类名在每个文件中是唯一的，所以它们不会冲突。

### 组合

CSS 模块可以将类选择器组合在一起，以在多个类之间重用样式规则。

例如：

```css title="styles.module.css" icon="file-code" theme={null}
.button {
  composes: background;
  color: red;
}

.background {
  background-color: blue;
}
```

这等同于编写：

```css title="styles.module.css" icon="file-code" theme={null}
.button {
  background-color: blue;
  color: red;
}

.background {
  background-color: blue;
}
```

使用 `composes` 时有两条规则：

<Info>
  **组合规则：** - `composes` 属性必须在任何常规 CSS 属性或声明之前 - 你只能在带有单个类名的简单选择器上使用 `composes`
</Info>

```css title="styles.module.css" icon="file-code" theme={null}
#button {
  /* 无效！`#button` 不是类选择器 */
  composes: background;
}

.button,
.button-secondary {
  /* 无效！`.button, .button-secondary` 不是简单选择器 */
  composes: background;
}
```

### 从单独的 CSS 模块文件中组合

你也可以从单独的 CSS 模块文件中组合：

```css title="background.module.css" icon="file-code" theme={null}
.background {
  background-color: blue;
}
```

```css title="styles.module.css" icon="file-code" theme={null}
.button {
  composes: background from "./background.module.css";
  color: red;
}
```

<Warning>
  当从单独文件组合类时，请确保它们不包含相同属性。

  CSS 模块规范指出，从具有冲突属性的单独文件中组合类是未定义行为：输出可能不同且不可靠。
</Warning>
