关于 bootstrap-color-system
用于调整 Bootstrap 6 Sass 与 CSS 令牌系统的颜色 Skill,帮助开发者选择合适层级配置色板、语义主题、颜色模式和运行时样式。
主要功能
- 01配置 OKLCH 色相与色阶
- 02映射语义主题角色
- 03自定义明暗模式
- 04运行时覆盖 CSS 变量
- 05生成颜色工具类
适用场景
- 01调整 Bootstrap 品牌色板
- 02添加语义主题颜色
- 03设置页面或租户专属颜色
- 04验证颜色令牌与对比度
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ twbs/ bootstrap --skill bootstrap-color-system安装后在 Claude Code 中输入/bootstrap-color-system确认已加载。
详细介绍
Bootstrap 6 颜色系统
Bootstrap 6 的颜色遵循固定的处理流程:少数几个 oklch() 色相生成完整色阶,其中一部分色阶获得语义角色,组件读取这些角色,而不是色相。自定义颜色时,需要选择正确的层进行修改,因此请先确定你的任务属于哪一层。
工作流
- 第 1 步:找到需要修改的层
- 第 2 步:基础色相和色阶
- 第 3 步:主题颜色
- 第 4 步:用于背景、前景和边框的层颜色
- 第 5 步:颜色模式
- 第 6 步:编译时覆盖
- 第 7 步:运行时覆盖
- 第 8 步:函数和工具
- 第 9 步:验证
第 1 步:找到需要修改的层
以下是处理流程及各阶段对应的文件:
- 基础色相 —
scss/_colors.scss将 16 个色相定义为oklch()标量,并将它们收集到$colors中。 - 颜色色阶 — 同一文件使用
color-mix()从每个色相派生出025–975各级,并将--blue-500、--red-200等输出到:root中。 - 主题颜色 —
scss/_theme.scss将语义名称(primary、danger等)逐一映射到这些色阶令牌。 - 根令牌 —
scss/_root.scss将每个主题角色输出为--<name>-<role>(--danger-bg-subtle),并输出层颜色令牌。 - 主题类 —
scss/helpers/_theme-colors.scss在@layer helpers中输出.theme-<name>,将--<name>-<role>重新映射到通用的--theme-<role>。 - 组件和工具 — 读取
--theme-*(并使用中性色作为回退值)和层令牌。没有任何内容会读取原始色相。
根据任务选择对应的层:更换品牌蓝属于第 1 阶段,新增语义颜色属于第 3 阶段,调整单个组件的样式需要修改组件令牌(参见 bootstrap-component 技能),而应用中的临时调整则应使用运行时 CSS 变量覆盖。
第 2 步:基础色相和色阶
每个色相都是一个为 500 级提供基准的 oklch() 值:
$blue: oklch(60% 0.24 240) !default;
这 16 个色相分别是蓝色、靛蓝、紫罗兰色、紫色、粉色、红色、橙色、琥珀色、黄色、黄绿色、绿色、蓝绿色、青色、棕色、灰色和铅灰色,另有 $white 和 $black。$colors 通过 defaults() 收集这些颜色,因此映射会进行合并,而不是替换。
色阶是自动生成的,而非手工挑选。每个色相的 025 050 100 200 300 400 级会与 $tint-color(var(--white))混合,600 700 800 900 950 975 级则会与 $shade-color(var(--black))混合,使用 $color-mix-space 指定的颜色空间(lab)。修改一个色相,就会重新派生出它的整套色阶。
向 $colors 合并新色相,即可自动获得完整色阶,以及基于 $colors 构建的所有颜色工具:
@use "bootstrap/scss/bootstrap" with (
$colors: (
"slate": oklch(55% 0.04 250),
)
);
色调和阴影百分比($color-tints、$color-shades)、混合空间以及混合目标,都可以用相同方式配置。也可以通过 $color-tokens 覆盖单个级别。
刻意使用 var(--white) / var(--black) 进行混合:这样可以让 color-mix() 保留在输出中,而不会被 CSS 压缩器简化为静态的 lab() 值。
第 3 步:主题颜色
scss/_theme.scss 中的 $theme-colors 定义了八种语义颜色——primary、accent、success、danger、warning、info、inverse、secondary——每种颜色都是一个包含九种角色的嵌套映射:
| 角色 | 用途 |
|---|---|
base | 派生其余颜色的原始品牌色 |
bg | 纯色背景,例如纯色按钮或徽章 |
bg-subtle | 用于警告、浅色按钮和提示框的淡色表面 |
bg-muted | 比浅色表面再深一级 |
fg | 浅色表面上的文本 |
fg-emphasis | 浅色表面上对比度更高的文本 |
contrast | 位于 base / bg 上的文本和图标 |
border | 浅色表面上的边框 |
focus-ring | 焦点轮廓颜色 |
大多数角色都是 light-dark(…) 配对值,并且每个值都是对色阶令牌的 var() 引用,而非字面颜色:
"danger": (
"base": var(--red-500),
"fg": light-dark(var(--red-600), var(--red-400)),
"bg-subtle": light-dark(var(--red-100), var(--red-900)),
"border": light-dark(var(--red-300), var(--red-600)),
"contrast": var(--white)
),
该映射会生成两类内容::root, :host 上的 --danger-fg 类令牌,以及一个将这些令牌赋给通用 --theme-fg、--theme-bg-subtle 等变量的 .theme-danger 类。这种间接引用正是设计目的——组件只要基于 --theme-* 编写,就能通过一条规则支持所有当前和未来的颜色。
在嵌套子树上使用 .theme-reset,可将这些 --theme-* 令牌设为 initial,让子元素恢复为组件默认值。
primary、success 和 danger 键是必需的;其他代码(链接、焦点环、表单状态、已选中控件)会读取它们的令牌。重命名或删除这些键会导致构建失败。
第 4 步:用于背景、前景和边框的分层颜色
中性色表面不属于 $theme-colors。scss/_theme.scss 中的三个独立映射负责定义这些颜色:
$theme-bgs→--bg-body、--bg-1至--bg-4(对比度逐渐增强的表面),以及--bg-white、--bg-black、--bg-transparent。$theme-fgs→--fg-body、--fg-1至--fg-4(强调程度逐渐降低)。$theme-borders→--border-body、--border-subtle、--border-muted、--border-emphasized。
将它们用作组件令牌中未应用主题时的回退值:var(--theme-bg-subtle, var(--bg-1))、var(--theme-border, var(--border-color))。请注意,--border-color 是 $root-tokens 中的独立全局令牌,是组件的默认边框颜色,与这组 --border-* 令牌不同。
与 $theme-colors 不同,这些映射都是扁平映射,因此可以轻松扩展,增加一个表面层级。所有四个映射都会通过 defaults() 合并,因此只需传入要更改的键。
第 5 步:颜色模式
Bootstrap 6 不会针对每种模式重新声明变量。每个自适应令牌都是一个 light-dark() 配对值,CSS 会根据继承的 color-scheme 进行解析:
:root, :host设置color-scheme: light dark,因此默认模式取决于操作系统的偏好。[data-bs-theme="dark"]和[data-bs-theme="light"]会在对应子树上设置color-scheme,强制使用指定模式。它适用于任何元素,支持嵌套,且不需要 JavaScript。
因此,切换模式只需设置一个属性;编写自适应颜色时,只需使用 light-dark(),而无需编写深色模式覆盖代码块。
对于 light-dark() 无法处理的情况,有两个 mixin:
// Non-color values can't go through light-dark()
@include color-mode(dark, $root: true) {
--shadow-strength: 2.4;
}
color-mode($mode, $root) 会遵循 $color-mode-type 配置,该配置默认为 "media-query"(生成 @media (prefers-color-scheme: …));将其设为 "data" 则改为生成 [data-bs-theme="…"] 选择器。color-scheme($name) 是普通的媒体查询封装,适用于始终需要使用媒体查询的情况。
自定义模式的工作方式相同:添加自己的 [data-bs-theme="blue"] 选择器,并在其中覆盖令牌。
步骤 6:编译时覆盖
通过 defaults() 构建的映射——$colors、$color-tokens、$root-tokens、$theme-colors、$theme-bgs、$theme-fgs、$theme-borders,以及每个组件的 $*-tokens——都会合并。只传入你要更改的键,传入 null 可移除某项。
嵌套的主题颜色映射会向下合并一层。要更改内置主题的某个角色,请传入该主题的整个子映射。部分子映射会替换该主题的其他角色。
调整现有主题颜色时,最简单的方法仍然是在下一层修改色相,这样所有派生值都会随之变化:
@use "bootstrap/scss/bootstrap" with (
$blue: oklch(58% 0.21 250)
);
要添加或重新设置主题颜色的样式,请通过主入口传入部分 $theme-colors 映射。defaults() 会保留内置项。除非替换整个子映射,否则请保留 primary、success 和 danger:
@use "bootstrap/scss/bootstrap" with (
$theme-colors: (
"brand": (
"base": var(--indigo-500),
"fg": light-dark(var(--indigo-600), var(--indigo-400)),
"fg-emphasis": light-dark(var(--indigo-800), var(--indigo-300)),
"bg": var(--indigo-500),
"bg-subtle": light-dark(var(--indigo-100), var(--indigo-900)),
"bg-muted": light-dark(var(--indigo-200), var(--indigo-800)),
"border": light-dark(var(--indigo-300), var(--indigo-600)),
"focus-ring": light-dark(color-mix(in oklch, var(--indigo-500) 50%, var(--bg-body)), color-mix(in oklch, var(--indigo-500) 75%, var(--bg-body))),
"contrast": var(--white)
)
)
);
如果你只想再添加一种主题颜色,而不需要工具类,可以跳过 Sass 配置,手动编写类。组件只依赖 --theme-* 令牌:
@layer helpers {
.theme-brand {
--theme-base: var(--purple-500);
--theme-bg: var(--purple-500);
--theme-bg-subtle: light-dark(var(--purple-100), var(--purple-900));
--theme-fg: light-dark(var(--purple-600), var(--purple-400));
--theme-border: light-dark(var(--purple-300), var(--purple-600));
--theme-contrast: var(--white);
}
}
这样,.theme-brand 就能用于所有支持主题的组件。代价是:工具类和 --brand-* 根令牌由 $theme-colors 生成,因此 .bg-brand 和 var(--brand-bg) 将不存在。
步骤 7:运行时覆盖
每个令牌都是 CSS 自定义属性,因此大多数颜色更改完全不需要重新编译:
/* Global — repeat on :host if you adopt the stylesheet in a shadow root */
:root,
:host {
--bs-primary-bg-subtle: #eef2ff;
}
/* One subtree */
.marketing-hero {
--bs-theme-bg-subtle: #eef2ff;
}
在 Sass 中,令牌名称不带前缀(例如 --primary-bg-subtle)。Bootstrap 的 dist 和 CDN CSS 会运行 PostCSS 来添加 --bs- 前缀,因此覆盖已发布的 CSS 时请使用 --bs-*,自行编译源码时则使用不带前缀的名称。
运行时覆盖适用于按页面或租户设置主题;编译时配置则用于更改系统的默认值。
步骤 8:函数和工具类
scss/_theme.scss 中的辅助函数用于跨颜色映射读取数据,主要用于生成工具类:
theme-color-values($role)— 返回颜色名称到该角色原始值的扁平映射。theme-color-refs($role)— 与上面相同,但值为var(--<name>-<role>)引用。theme-token-refs($map, $prefix)— 用于层级颜色映射的对应函数。theme-opacity-values($var, $fallback)— 使用color-mix()与transparent混合生成的不透明度阶梯。
scss/_functions.scss 中的 color-contrast($background) 使用 WCAG 对比度算法,返回浅色、深色或黑色前景色。它适用于 Sass 颜色值,不适用于 var() 引用,因此用于构建时色板和生成的类;$theme-colors 中的 contrast 角色则用于运行时。
生成的工具类遵循角色名称:每种主题颜色都有 .fg-primary、.fg-emphasis-primary、.fg-contrast-primary、.bg-primary、.bg-subtle-primary、.bg-muted-primary、.border-primary 和 .border-subtle-primary。层级颜色也会生成同样的工具类(.bg-1 至 .bg-4、.fg-1 至 .fg-4、.border-subtle);不透明度则按 10 为步长,以数字阶梯应用于相同的类名,例如 .fg-50、.bg-70、.border-30。
如果你想为整个元素设置主题,而不是只重新着色某个属性,请改用 .theme-*。
步骤 9:验证
- 运行
npm run css-lint,然后运行npm run css。 - 在编译后的
dist/css/bootstrap.css中搜索预期的令牌(--bs-primary-bg-subtle、--bs-slate-500),确认它们已生成。 - 检查两种颜色模式:操作系统偏好设置、
data-bs-theme="dark",以及其中嵌套的data-bs-theme="light"。 - 验证所有新增主题颜色的对比度——至少检查两种模式下
bg上的contrast,以及bg-subtle上的fg。 - 如果你在
$colors或$theme-colors中添加或移除了条目,请确认生成的工具类和.theme-*类已相应更改,并确认npm run docs-build仍能通过(文档会根据这些映射渲染色板)。