Skip to content

Bun 的打包器内置支持 CSS,具有以下特性:

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

转译

Bun 的 CSS 打包器让您可以使用现代/未来 CSS 特性,而无需担心浏览器兼容性——这都归功于其默认启用的转译和供应商前缀功能。

Bun 的 CSS 解析器和打包器是 LightningCSS 的直接 Rust → Zig 移植,打包方法受到 esbuild 的启发。转译器将现代 CSS 语法转换为向后兼容的等效版本,可在所有浏览器上工作。

NOTE

非常感谢 LightningCSS 和 esbuild 作者的出色工作。

浏览器兼容性

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

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

语法降级

嵌套

CSS 嵌套规范允许您通过相互嵌套选择器来编写更简洁和直观的样式表。无需在 CSS 文件中重复父选择器,您可以在父块内直接编写子样式。

scss
/* 使用嵌套 */
.card {
  background: white;
  border-radius: 4px;

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

  .content {
    padding: 1rem;
  }
}

Bun 的 CSS 打包器自动将此嵌套语法转换为适用于所有浏览器的传统扁平 CSS:

css
/* 编译输出 */
.card {
  background: white;
  border-radius: 4px;
}

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

.card .content {
  padding: 1rem;
}

您还可以在选择器内嵌套媒体查询和其他 at-rule,无需重复选择器模式:

scss
.responsive-element {
  display: block;

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

这编译为:

css
.responsive-element {
  display: block;
}

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

颜色混合

color-mix() 函数提供了一种简单的方法,根据指定比例在选定的颜色空间中混合两种颜色。这个强大的功能让您无需手动计算结果值即可创建颜色变体。

scss
.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
.button {
  /* 计算为确切的结果颜色 */
  background-color: #b31a1a;
}

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

此功能对于创建具有编程派生的阴影、色调和强调色的颜色系统特别有用,无需预处理器或自定义工具。

相对颜色

CSS 现在允许您使用相对颜色语法修改单个颜色组件。这个强大的功能让您可以通过调整特定属性(如亮度、饱和度或单个通道)来创建颜色变体,而无需重新计算整个颜色。

css
.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-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 具有显著优势。这些颜色空间可以表示超出标准 RGB 色域的颜色,从而实现更生动和视觉上一致的设计。

css
.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
.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() 函数提供了一种标准化方式,在各种预定义颜色空间中指定颜色,将您的设计选项扩展到传统 RGB 空间之外。这允许您访问更宽的色域并创建更生动的设计。

css
.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
.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
.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
.easy-theming {
  --primary: #00ffff;
  --primary-light: #33ffff;
  --primary-dark: #00b3b3;
  --primary-muted: #339999;
}

HWB 模型特别容易为设计系统创建系统颜色变体,提供了一种比直接使用 RGB 或 HSL 创建一致色调和暗色更直观的方法。

颜色表示法

现代 CSS 引入了更直观和简洁的颜色表达方式。空格分隔的颜色语法消除了 RGB 和 HSL 值中对逗号的需求,而带 alpha 通道的十六进制颜色提供了一种指定透明度的紧凑方式。

css
.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
.modern-styling {
  /* 为旧版浏览器转换为逗号格式 */
  color: rgb(50, 100, 200);

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

  /* 需要时将 Hex+alpha 转换为 rgba */
  background-color: rgba(0, 170, 255, 0.5);

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

此转换过程让您编写更清晰、更现代的 CSS,同时确保您的样式在所有浏览器上正常工作。

light-dark() 颜色函数

light-dark() 函数提供了一种优雅的解决方案,用于实现尊重用户系统偏好的配色方案,无需复杂的媒体查询。此函数接受两个颜色值,并根据当前配色方案上下文自动选择合适的颜色。

css
: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;
}

对于尚不支持此功能的浏览器,Bun 的 CSS 打包器将其转换为使用带有适当回退的 CSS 变量:

css
:root {
  --lightningcss-light: initial;
  --lightningcss-dark: ;
  color-scheme: light dark;
}

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

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

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

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

这种方法为您提供了一种干净的方式来处理亮色和暗色主题,无需复制样式或编写复杂的媒体查询,同时与尚不原生支持此功能的浏览器保持兼容性。

逻辑属性

CSS 逻辑属性允许您相对于文档的书写模式和文本方向定义布局、间距和大小,而不是物理屏幕方向。这对于创建真正国际化的布局至关重要,这些布局可自动适应不同的书写系统。

css
.multilingual-component {
  /* 适应书写方向的边距 */
  margin-inline-start: 1rem;

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

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

  /* 尊重书写模式的尺寸 */
  inline-size: 80%;
  block-size: auto;
}

对于不完全支持逻辑属性的浏览器,Bun 的 CSS 打包器将它们编译为具有适当方向调整的物理属性:

css
/* 对于从左到右的语言 */
.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() 选择器,会自动生成额外的回退,确保您的布局在所有浏览器和书写系统上正常工作。这使得创建国际化设计变得简单得多,同时与旧版浏览器保持兼容性。

:dir() 选择器

:dir() 伪类选择器允许您根据文本方向(RTL 或 LTR)设置元素样式,提供了一种强大的方法来创建无需 JavaScript 的方向感知设计。此选择器根据文档或显式方向属性确定的方向性匹配元素。

css
/* 根据文本方向应用不同样式 */
.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
/* 转换为使用基于语言的选择器作为回退 */
.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;
}

此转换让您编写方向感知的 CSS,在所有浏览器上可靠工作,即使那些尚不原生支持 :dir() 选择器的浏览器。如果不支持 :lang() 的多个参数,会自动提供进一步的回退。

:lang() 选择器

:lang() 伪类选择器允许您根据元素所在的语言定位元素,使其易于应用特定于语言的样式。现代 CSS 允许 :lang() 选择器接受多个语言代码,让您更有效地分组特定于语言的规则。

css
/* 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
/* 使用 :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 中的重复。

css
/* 而不是单独编写这些 */
/* 
.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
/* 使用 -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;
}

:not() 选择器

:not() 伪类允许您排除匹配特定选择器的元素。此选择器的现代版本接受多个参数,让您使用单个简洁的选择器排除多个模式。

css
/* 选择除 primary 和 secondary 变体之外的所有按钮 */
button:not(.primary, .secondary) {
  background-color: #f5f5f5;
  border: 1px solid #ddd;
}

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

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

css
/* 转换为使用 :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
/* 甚至更多回退以获得最大兼容性 */
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
.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
.dynamic-sizing {
  width: clamp(200px, 50%, 800px);
  padding: 15px;
  transform: rotate(35.36deg);
  --scale-factor: 1.953125;
  font-size: calc(16px * var(--scale-factor));
}

这种方法让您编写更具表现力和可维护的 CSS,具有有意义的数学关系,然后编译为优化的值,以获得最大的浏览器兼容性和性能。

媒体查询范围

现代 CSS 支持直观的范围语法用于媒体查询,允许您使用比较运算符(如 <><=>=)指定断点,而不是更冗长的 min-max- 前缀。此语法更具可读性,与我们正常思考值和范围的方式匹配。

css
/* 使用比较运算符的现代语法 */
@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
/* 转换为传统 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 引入了几个现代简写属性,提高了代码可读性和可维护性。Bun 的 CSS 打包器确保这些方便的简写在所有浏览器上工作,必要时将它们转换为它们的长写等效版本。

css
/* 对齐简写 */
.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
.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 特性,允许您通过在两个相邻位置指定相同的颜色在渐变中创建硬颜色停止。这创建了尖锐的过渡而不是平滑的淡入淡出,这对于创建条纹、色带和其他多色设计很有用。

css
.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
.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
.native-interface {
  /* 使用系统的默认 UI 字体 */
  font-family: system-ui;
}

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

对于不支持 system-ui 的浏览器,Bun 的 CSS 打包器自动将其扩展为全面的跨平台字体系列:

css
.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;
}

这种方法让您在源代码中只需编写 system-ui,同时确保您的界面正确适应所有操作系统和浏览器。扩展的字体系列包括适用于 macOS/iOS、Windows、Android、Linux 的适当系统字体,以及旧版浏览器的回退。

CSS 模块

Bun 的打包器还支持打包 CSS 模块,除了常规 CSS 外,还支持以下特性:

  • 自动检测 CSS 模块文件(.module.css),无需配置
  • 组合(composes 属性)
  • 将 CSS 模块导入到 JSX/TSX
  • 对无效使用 CSS 模块的警告/错误

CSS 模块是具有 .module.css 扩展名的 CSS 文件,其中所有类名和动画都限定在文件范围内。这有助于您避免类名冲突,因为 CSS 声明默认是全局作用域的。

在内部,Bun 的打包器将本地作用域的类名转换为唯一标识符。

入门

创建具有 .module.css 扩展名的 CSS 文件:

css
.button {
  color: red;
}
css
.button {
  color: blue;
}

然后您可以将此文件导入到 TSX 文件中,例如:

tsx
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 模块文件获得的 styles 对象将是一个对象,其中所有类名作为键,它们的唯一标识符作为值:

ts
import styles from "./styles.module.css";
import otherStyles from "./other-styles.module.css";

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

这将输出:

ts
{
  button: "button_123";
}

{
  button: "button_456";
}

如您所见,类名对于每个文件都是唯一的,避免了任何冲突!

组合

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

例如:

css
.button {
  composes: background;
  color: red;
}

.background {
  background-color: blue;
}

等同于编写:

css
.button {
  background-color: blue;
  color: red;
}

.background {
  background-color: blue;
}

使用 composes 时,请记住几条规则:

css
#button {
  /* 无效!`#button` 不是类选择器 */
  composes: background;
}

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

从单独的 CSS 模块文件组合

您还可以从单独的 CSS 模块文件组合类:

css
.background {
  background-color: blue;
}
css
.button {
  composes: background from "./background.module.css";
  color: red;
}

Bun学习网由www.bunjs.com.cn整理维护