mcpField
B
bootstrap-utility-api

bootstrap-utility-api

github.com/twbs设计与 UI175.0k346 次安装今天更新
代码仓库

关于 bootstrap-utility-api

面向 Bootstrap 6 样式开发者的实用工具 API 指南,介绍如何通过 Sass 的 `$utilities` 映射生成、扩展、调整和精简工具类。

主要功能

  1. 01理解工具类生成流程
  2. 02定义与扩展工具类
  3. 03生成响应式及状态变体
  4. 04组合自定义属性与选择器
  5. 05精简生成的 CSS

适用场景

  1. 01为项目添加自定义工具类
  2. 02调整默认工具类及其变体
  3. 03减少项目生成的工具类 CSS

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/twbs/bootstrap --skill bootstrap-utility-api

安装后在 Claude Code 中输入/bootstrap-utility-api确认已加载。

详细介绍

Bootstrap 6 工具类 API

Bootstrap 中的每个工具类都由同一个 Sass 映射 $utilities 生成。每个条目描述一组类:它设置的属性、接受的值,以及要生成哪些变体。自定义工具类意味着编辑该映射,而不是编写 CSS。

工作流

  • 步骤 1:了解生成方式
  • 步骤 2:阅读工具类定义
  • 步骤 3:添加工具类
  • 步骤 4:修改、重命名或移除默认工具类
  • 步骤 5:生成响应式、状态、打印和深色变体
  • 步骤 6:使用自定义属性和高级选择器组合值
  • 步骤 7:精简生成的 CSS
  • 步骤 8:向 Bootstrap 本身添加工具类
  • 步骤 9:验证

步骤 1:了解生成方式

scss/utilities/_api.scss 是完整的处理流程:

@include generate-utility-at-properties($utilities);

@layer utilities {
  @include generate-utilities-loop($utilities, $breakpoints);
}

动手前,值得了解以下三点:

  • 工具类位于层叠顺序的最后一层,因此无需 !important 就能覆盖组件样式。只有通过 important: true 启用该选项的组才会添加它。
  • @property 注册在层外进行。 工具类赋值的每个自定义属性(--bg、--fg、--bc、--rounded-size 等)都会以 syntax: "*"; inherits: false 注册,因此应用 .border-inverse 不会将其组合值泄漏到后代元素。为自定义属性赋值的新工具类也会自动执行此操作。
  • 映射配置在 config 模块上,而非 bootstrap 上。 $utilities 在 scss/_config.scss 中声明,仅在 scss/_utilities.scss 中填充(该文件通过 @use "config" as * 加载 config)。配置错误的模块会失败:
// Does NOT work — "This variable was not declared with !default in the @used module."
@use "bootstrap/scss/bootstrap" with (
  $utilities: (…)
);

// Works — configure config first, then load Bootstrap
@use "bootstrap/scss/config" with (
  $utilities: (…)
);
@use "bootstrap/scss/bootstrap";

这同样适用于 _config.scss 中的任何变量($radius、$spacers、$breakpoints、$zindex-levels)。bootstrap.scss 转发的分部文件中声明的变量($root-tokens、$colors、$blue)则可以直接在 bootstrap 上配置。


步骤 2:阅读工具类定义

一组工具类是一个映射。最简单的形式需要两个键:

"overflow": (
  property: overflow,
  values: auto hidden visible scroll,
),

generate-utility() 验证的完整选项如下:

键必填功能
property是属性名称、以空格分隔的名称列表,或属性到值的映射
values是列表(类后缀等于值)或映射(键会成为后缀;null 键会省略后缀)
class否用于替代属性名称的类名
selector否class(默认值)、attr-starts 或 attr-includes
child-selector否后代选择器,会包裹在 :where() 中,以使特异性为零
variables否要输出的自定义属性——静态值映射,或一个列表,列表中的每项都会接收工具类值
state否要生成的伪类变体,例如 hover focus
responsive否为每个断点生成一个类(默认值为 false)
print否生成带 print: 前缀的类(默认值为 false)
dark否在 prefers-color-scheme: dark 中生成带 dark: 前缀的类(默认值为 false)
important否附加 !important(默认值为 false)
enabled否设为 false 可禁止输出,同时保留定义(默认值为 true)

生成器会在处理过程中进行验证,因此很容易发现错误:缺少 property 或 values 会触发硬性 @error,responsive 不是布尔值会触发硬性 @error,键名拼写错误则会触发 @warn,并列出有效键名。


步骤 3:添加工具类

你的映射会与 Bootstrap 默认映射合并,因此只需传入新增内容:

@use "bootstrap/scss/config" with (
  $utilities: (
    "cursor": (
      property: cursor,
      class: cursor,
      responsive: true,
      values: auto pointer grab,
    ),
  )
);
@use "bootstrap/scss/bootstrap";

这会生成 .cursor-auto、.cursor-pointer、.cursor-grab,以及从 .sm:cursor-* 到 .2xl:cursor-* 的类。

值的形式决定类名:

// List — suffix is the value itself: .cursor-pointer
values: auto pointer grab,

// Map — keys become suffixes: .tint-brand
values: (brand: var(--purple-500), muted: var(--gray-200)),

// null key — no suffix at all: .shout
values: (null: uppercase),

步骤 4:修改、重命名或移除默认工具

合并采用浅层合并:提供现有组的键会替换整个组。只覆盖一个选项而省略其余选项会明确报错 —

// Errors: "Utility is missing required `property` key"
"overflow": (
  responsive: true,
  values: visible hidden scroll auto,
),

因此,请从 scss/_utilities.scss 复制完整定义并添加你的更改:

@use "bootstrap/scss/config" with (
  $utilities: (
    // Make overflow responsive
    "overflow": (
      property: overflow,
      values: auto hidden visible scroll,
      responsive: true,
    ),
    // Remove a family entirely
    "width": null,
    // Rename .ms-* to v4-style .ml-*: drop the original, add a replacement
    "margin-start": null,
    "margin-start-alias": (
      property: margin-inline-start,
      class: ml,
      responsive: true,
      values: (0: 0, 1: var(--spacer-1), 2: var(--spacer-2), auto: auto),
    ),
  )
);
@use "bootstrap/scss/bootstrap";

注意最后一组中的 CSS 令牌。配置 config 的文件无法读取 Bootstrap 的 Sass 成员——$spacers、$negative-spacers 和 map-merge-multiple() 之类的辅助函数此时尚未进入作用域——因此,请将值重新写成 CSS 令牌(var(--spacer-2) 会随间距刻度变化)或字面值。

若要扩展现有系列而不复制其定义,请注册一个重用相同 class 的新组:

"width-extra": (
  property: width,
  class: w,
  responsive: true,
  values: (10: 10%, 15: 15%),
),

这样会在 Bootstrap 的 .w-25 … .w-100 旁添加 .w-10 和 .w-15,通常是更好的选择——即使 Bootstrap 更新并更改原始组,它也能保留。

如果希望定义继续显示在映射中,请优先使用 enabled: false,而不是 null(这在共享配置中很有用:组有文档说明,但有意关闭)。


步骤 5:生成响应式、状态、打印和深色变体

v6 使用前缀,而不是中缀或后缀。这四种变体类型都会与基础类名组合:

选项生成的类备注
responsive: true.md:cursor-pointer为 $breakpoints 中的每个键生成一轮;在 CSS 中写作 .md\:
state: hover focus.hover:cursor-pointer选择器为 .hover\:cursor-pointer:hover
print: true.print:d-none包裹在 @media print 中
dark: true.dark:bg-black包裹在 @media (prefers-color-scheme: dark) 中

responsive 和 state 可以叠加,生成 .md:hover:cursor-pointer。每种变体都会增加生成的 CSS,因此应按组启用,而不是全局启用。


步骤 6:使用自定义属性和高级选择器组合值

大多数类似颜色的工具不会直接设置属性。它们会先赋值给一个局部自定义属性,再使用该属性,因此才能实现不透明度和组合效果:

"tint": (
  property: (
    "--tint": null,
    "background-color": var(--tint),
  ),
  class: tint,
  values: (brand: var(--purple-500)),
),

属性映射中的 null 值表示“接收该工具的值”;其他条目则按原样输出。上面的配置会生成:

.tint-brand {
  --tint: var(--purple-500);
  background-color: var(--tint);
}

相关机制:

  • variables 会输出额外的自定义属性。使用映射时,每个属性都会在该组的每个类上取得静态值;使用列表时,每个属性都会接收该工具的值。
  • 属性映射与映射值。 当 property 是映射,且某个 values 条目本身是以属性名为键的映射时,每个属性都会采用各自的值——适用于一个组需要以不同值设置多个相关属性的情况。
  • selector: attr-starts / attr-includes 会针对 [class^="…"] / [class*="…"],而非某个类进行匹配,并且需要 class 键。Bootstrap 使用它让 .ratio-16x9 通过 --ratio 设置 aspect-ratio。
  • child-selector 会将规则包裹在 :where() 中,例如 :where(.stack-gap-1 > *)。零特异性意味着子元素自身的样式仍具有优先权。

在 Sass 中,自定义属性名称不带前缀。Bootstrap 的 dist 和 CDN CSS 会通过 PostCSS 添加 --bs-,因此自行编译源代码时,自定义属性名称会保持无前缀。


步骤 7:精简生成的 CSS

工具类是 Bootstrap CSS 中占比最大的部分,而映射是精简 CSS 最省事的地方:

  1. 如果不需要组件,请从仅包含工具类的入口点开始:

    @use "bootstrap/scss/config" with ($utilities: (…));
    @use "bootstrap/scss/bootstrap-utilities";
    
  2. 将未使用的组设为 null(或设为 enabled: false),而不是依赖压缩器或清理步骤。

  3. 对只在一个断点使用的组关闭 responsive——一个响应式组会生成自身的六份副本。

  4. 如果只需要几个步长,请缩小 values 映射,而不是删除整个组。

有关整体优化,请参阅 优化,其中还介绍了 Lightning CSS 和清理。


第 8 步:为 Bootstrap 本身添加工具类

为框架而非项目贡献工具类时:

  1. 在 scss/_utilities.scss 的 $utilities 映射中,靠近相关分组添加该分组,并用 // scss-docs-start utils-<name> / // scss-docs-end utils-<name> 标记包裹。
  2. 如果工具类需要与不透明度或主题颜色交互,优先通过自定义属性组合,并复用现有 token 值($spacers、$util-opacity、theme-color-refs()),而不是使用字面值。
  3. 在 site/src/content/docs/utilities/ 中对应的页面为其编写文档,用 <ScssDocs name="utils-<name>" file="scss/_utilities.scss" /> 渲染定义;如果是新页面,还要在 site/data/sidebar.yml 中添加条目。
  4. 在 scss/tests/utilities/_api.test.scss 中添加测试覆盖,直接调用生成器 mixin,并传入 fixture 映射。
  5. 运行 npm run css。其中的 css-docs 步骤会重新生成 dist/css/bootstrap-utilities.metadata.json,文档会读取该文件——请将它与更改一起提交。

第 9 步:验证

  1. 运行 npm run css-lint,然后运行 npm run css。
  2. 对编译后的 CSS 执行 grep,检查预期的类,包括转义后的变体(\.md\\:cursor-pointer),并确认已移除的内容不再存在。
  3. 确认新的自定义属性出现在文件顶部的 @property 块中——如果缺少某个属性,说明该工具类没有通过 property 或 variables 赋值。
  4. 留意 Sass 输出中有关未知键的 @warn 行;这是发现选项拼写错误并被静默忽略的最快信号。
  5. 在浏览器中检查优先级:工具类应仅通过层级顺序覆盖组件样式,无需使用 !important。

评论

支持 Markdown