bootstrap-color-system
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBootstrap 6 color system
Bootstrap 6 颜色系统
Bootstrap 6 colors flow through a fixed pipeline: a handful of hues become full scales, a subset of those scales gets semantic roles, and components read the roles — never the hues. Customizing colors means picking the right layer to change, so start by identifying which one your task belongs to.
oklch()Bootstrap 6 的颜色遵循一套固定的处理流程:少量 色相值会生成完整的色阶,部分色阶被赋予语义角色,组件只会读取这些角色——绝不会直接使用色相值。自定义颜色意味着要选择正确的层级进行修改,因此首先要确定你的任务属于哪一层。
oklch()Workflow
工作流程
- Step 1: Locate the layer you need to change
- Step 2: Base hues and scales
- Step 3: Theme colors
- Step 4: Layer colors for backgrounds, foregrounds, and borders
- Step 5: Color modes
- Step 6: Compile-time overrides
- Step 7: Runtime overrides
- Step 8: Functions and utilities
- Step 9: Verify
- 步骤1:确定你需要修改的层级
- 步骤2:基础色相与色阶
- 步骤3:主题色
- 步骤4:背景、前景与边框的层级颜色
- 步骤5:颜色模式
- 步骤6:编译时覆盖
- 步骤7:运行时覆盖
- 步骤8:函数与工具类
- 步骤9:验证
Step 1: Locate the layer you need to change
步骤1:确定你需要修改的层级
The pipeline, with the file that owns each stage:
- Base hues — defines 16 hues as
scss/_colors.scssscalars and collects them inoklch().$colors - Color scales — the same file derives steps –
025from each hue with975, emittingcolor-mix(),--blue-500, and so on into--red-200.:root - Theme colors — maps semantic names (
scss/_theme.scss,primary, …) onto those scale tokens, one role at a time.danger - Root tokens — emits every theme role as
scss/_root.scss(--<name>-<role>) plus the layer color tokens.--danger-bg-subtle - Theme classes — outputs
scss/helpers/_theme-colors.scssin.theme-<name>, remapping@layer helpersonto the generic--<name>-<role>.--theme-<role> - Components and utilities — read (with a neutral fallback) and the layer tokens. Nothing reads a raw hue.
--theme-*
Match the task to the layer: a different brand blue is stage 1, a new semantic color is stage 3, restyling one component is a component token (see the skill), and a one-off tweak in an app is a runtime CSS variable override.
bootstrap-component整个处理流程及每个阶段对应的文件如下:
- 基础色相 — 中定义了16个色相作为
scss/_colors.scss标量值,并将它们收集在oklch()变量中。$colors - 色阶 — 同一个文件通过 从每个色相衍生出
color-mix()–025的色阶,生成975、--blue-500等变量并挂载到--red-200上。:root - 主题色 — 将语义名称(
scss/_theme.scss、primary等)逐一映射到这些色阶token上,每个名称对应一个角色。danger - 根token — 将每个主题角色生成为
scss/_root.scss格式的变量(如--<名称>-<角色>)以及层级颜色token。--danger-bg-subtle - 主题类 — 在
scss/helpers/_theme-colors.scss中输出@layer helpers类,将.theme-<名称>重新映射到通用的--<名称>-<角色>变量上。--theme-<角色> - 组件与工具类 — 读取 变量(带有中性色兜底)以及层级token。没有任何组件会直接读取原始色相值。
--theme-*
将任务对应到相应层级:修改品牌蓝色属于第1阶段,新增语义色属于第3阶段,调整单个组件样式属于组件token范畴(参见 skill),而应用中的一次性微调则属于运行时CSS变量覆盖。
bootstrap-componentStep 2: Base hues and scales
步骤2:基础色相与色阶
Each hue is a single value that anchors step 500:
oklch()scss
$blue: oklch(60% 0.24 240) !default;The 16 hues are blue, indigo, violet, purple, pink, red, orange, amber, yellow, lime, green, teal, cyan, brown, gray, and pewter, plus and . collects them through , so the map merges rather than replaces.
$white$black$colorsdefaults()Scales are generated, not hand-picked. Every hue is mixed toward () for steps and toward () for , in the color space (). Change a hue and its whole scale re-derives.
$tint-colorvar(--white)025 050 100 200 300 400$shade-colorvar(--black)600 700 800 900 950 975$color-mix-spacelabAdd a hue by merging into — you get its full scale and any color utilities built from automatically:
$colors$colorsscss
@use "bootstrap/scss/bootstrap" with (
$colors: (
"slate": oklch(55% 0.04 250),
)
);Tint and shade percentages (, ), the mixing space, and the mix targets are all configurable the same way. Individual steps can be overridden through .
$color-tints$color-shades$color-tokensMixing happens against / on purpose: it keeps live in the output instead of letting the CSS minifier flatten it into static values.
var(--white)var(--black)color-mix()lab()每个色相都是一个单独的 值,作为色阶中500号的基准:
oklch()scss
$blue: oklch(60% 0.24 240) !default;这16个色相分别是 blue、indigo、violet、purple、pink、red、orange、amber、yellow、lime、green、teal、cyan、brown、gray、pewter,另外还有 和 。 通过 收集这些色相,因此映射表是合并而非替换的。
$white$black$colorsdefaults()色阶是自动生成的,而非手动挑选的。每个色相在 指定的颜色空间()中,向 ()混合生成 号浅色色阶,向 ()混合生成 号深色色阶。修改一个色相,它的整个色阶都会重新生成。
$color-mix-spacelab$tint-colorvar(--white)025、050、100、200、300、400$shade-colorvar(--black)600、700、800、900、950、975通过合并到 中来添加新的色相——你会自动获得它的完整色阶,以及所有基于 构建的颜色工具类:
$colors$colorsscss
@use "bootstrap/scss/bootstrap" with (
$colors: (
"slate": oklch(55% 0.04 250),
)
);浅色与深色的百分比(、)、混合空间以及混合目标都可以用同样的方式配置。单个色阶可以通过 覆盖。
$color-tints$color-shades$color-tokens混合操作特意基于 / 进行:这样可以让输出的CSS中保留 的动态计算,而不会被CSS压缩器扁平化为静态的 值。
var(--white)var(--black)color-mix()lab()Step 3: Theme colors
步骤3:主题色
$theme-colorsscss/_theme.scssprimaryaccentsuccessdangerwarninginfoinversesecondary| Role | What it's for |
|---|---|
| The raw brand color the rest is derived from |
| Solid background, e.g. a solid button or badge |
| Tinted surface for alerts, subtle buttons, callouts |
| One step stronger than subtle |
| Text on a subtle surface |
| Higher-contrast text on a subtle surface |
| Text and icons sitting on |
| Borders on subtle surfaces |
| Focus outline color |
Most roles are pairs, and every value is a reference to a scale token rather than a literal color:
light-dark(…)var()scss
"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)
),The map produces two things: -style tokens on , and a class that assigns them to the generic , , and friends. That indirection is the whole point — a component written against supports every color, current and future, with one rule.
--danger-fg:root, :host.theme-danger--theme-fg--theme-bg-subtle--theme-*Use on a nested subtree to set those tokens to and return children to their component defaults.
.theme-reset--theme-*initialThe , , and keys are required; other code (links, focus rings, form states, checked controls) reads their tokens. Renaming or removing them breaks the build.
primarysuccessdangerscss/_theme.scss$theme-colorsprimaryaccentsuccessdangerwarninginfoinversesecondary| 角色 | 用途 |
|---|---|
| 品牌原色,其他角色都基于它衍生 |
| 实色背景,例如实心按钮或徽章 |
| 浅色调表面,用于提示框、浅按钮、标注等 |
| 比 subtle 深一级的背景 |
| 浅色背景上的文字颜色 |
| 浅色背景上的高对比度强调文字 |
| 位于 |
| 浅色表面上的边框颜色 |
| 焦点轮廓颜色 |
大多数角色都是 成对的值,每个值都是对色阶token的 引用,而非固定颜色值:
light-dark(…)var()scss
"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)
),这个映射会生成两部分内容:一是挂载在 上的 格式的token,二是 类,它将这些token赋值给通用的 、 等变量。这种间接层正是核心意义所在——基于 编写的组件只需一套规则,就能支持所有现有和未来的颜色。
:root, :host--danger-fg.theme-danger--theme-fg--theme-bg-subtle--theme-*在嵌套的子树上使用 可以将这些 token重置为 ,让子元素恢复到组件的默认样式。
.theme-reset--theme-*initialprimarysuccessdangerStep 4: Layer colors for backgrounds, foregrounds, and borders
步骤4:背景、前景与边框的层级颜色
Neutral surfaces don't live in . Three separate maps in cover them:
$theme-colorsscss/_theme.scss- →
$theme-bgs,--bg-bodythrough--bg-1(increasingly contrasty surfaces), plus--bg-4,--bg-white,--bg-black.--bg-transparent - →
$theme-fgs,--fg-bodythrough--fg-1(decreasing emphasis).--fg-4 - →
$theme-borders,--border-body,--border-subtle,--border-muted.--border-emphasized
Use these as the unthemed fallbacks in component tokens: , . Note that is a separate global token in — the default border color for components — distinct from this family.
var(--theme-bg-subtle, var(--bg-1))var(--theme-border, var(--border-color))--border-color$root-tokens--border-*Unlike , these are flat maps, which makes them easy to extend with an extra surface step. All four maps merge through , so pass only the keys you are changing.
$theme-colorsdefaults()中性色表面不属于 的范畴。 中有三个独立的映射表来管理它们:
$theme-colorsscss/_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
在组件token中将这些用作无主题时的兜底值:例如 、。注意 是 中一个独立的全局token——即组件的默认边框颜色——和这里的 系列是不同的。
var(--theme-bg-subtle, var(--bg-1))var(--theme-border, var(--border-color))--border-color$root-tokens--border-*和 不同,这些都是扁平映射,因此很容易扩展新增的表面层级。所有四个映射表都通过 合并,因此只需传入你要修改的键即可。
$theme-colorsdefaults()Step 5: Color modes
步骤5:颜色模式
Bootstrap 6 does not redeclare variables per mode. Every adaptive token is a pair, and CSS resolves it from the inherited :
light-dark()color-scheme- sets
:root, :host, so the default is whatever the OS prefers.color-scheme: light dark - and
[data-bs-theme="dark"]set[data-bs-theme="light"]on that subtree, forcing a mode. It works on any element, nests, and needs no JavaScript.color-scheme
So switching modes is a matter of setting one attribute, and authoring adaptive colors is a matter of using instead of writing a dark-mode override block.
light-dark()Two mixins exist for the cases can't cover:
light-dark()scss
// 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)Custom modes work the same way: add your own selector and override tokens inside it.
[data-bs-theme="blue"]Bootstrap 6 不会为每种模式重新声明变量。每个自适应token都是一个 成对值,CSS会根据继承的 值来解析它:
light-dark()color-scheme- 设置了
:root, :host,因此默认模式跟随系统偏好。color-scheme: light dark - 和
[data-bs-theme="dark"]会在对应子树上设置[data-bs-theme="light"],强制使用指定模式。它可以作用于任何元素,支持嵌套,且无需JavaScript。color-scheme
因此切换模式只需设置一个属性,而编写自适应颜色只需使用 ,无需编写暗色模式的覆盖代码块。
light-dark()对于 无法覆盖的场景,有两个mixin可用:
light-dark()scss
// 非颜色值无法通过 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)自定义模式的工作方式相同:添加你自己的 选择器,然后在其中覆盖token即可。
[data-bs-theme="blue"]Step 6: Compile-time overrides
步骤6:编译时覆盖
Maps built with — , , , , , , , and every component — merge. Pass only the keys you're changing, and pass to remove one.
defaults()$colors$color-tokens$root-tokens$theme-colors$theme-bgs$theme-fgs$theme-borders$*-tokensnullNested theme-color maps merge one level deep. To change one role of a built-in theme, pass the whole sub-map for that theme. A partial sub-map replaces the theme's other roles.
Retuning an existing theme color is still easiest one layer down — change the hue and everything derived from it follows:
scss
@use "bootstrap/scss/bootstrap" with (
$blue: oklch(58% 0.21 250)
);To add or restyle a theme color, pass a partial map through the main entrypoint. keeps the built-ins. Keep , , and unless you replace their whole sub-map:
$theme-colorsdefaults()primarysuccessdangerscss
@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)
)
)
);When all you want is one more theme color without utilities, skip the Sass config and write the class yourself. Components only care about the tokens:
--theme-*scss
@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-brandvar(--brand-bg)使用 构建的映射表——包括 、、、、、、,以及所有组件的 ——都会合并。只需传入你要修改的键,传入 则可以删除某个键。
defaults()$colors$color-tokens$root-tokens$theme-colors$theme-bgs$theme-fgs$theme-borders$*-tokensnull嵌套的主题色映射只会合并一层。要修改内置主题的某个角色,需要传入该主题的完整子映射。如果传入部分子映射,会替换掉该主题的其他角色。
调整现有主题色最简单的方式还是修改上一层——改色相,所有衍生的内容都会自动更新:
scss
@use "bootstrap/scss/bootstrap" with (
$blue: oklch(58% 0.21 250)
);要添加或重新设计主题色,可以通过主入口传入部分 映射。 会保留内置的主题色。除非你要替换整个子映射,否则请保留 、 和 这三个键:
$theme-colorsdefaults()primarysuccessdangerscss
@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配置,直接自己写类。组件只关心 token:
--theme-*scss
@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);
}
}这样 就可以在所有支持主题的组件上使用了。代价是:工具类和 根token是从 生成的,因此 和 不会存在。
.theme-brand--brand-*$theme-colors.bg-brandvar(--brand-bg)Step 7: Runtime overrides
步骤7:运行时覆盖
Every token is a CSS custom property, so most color changes need no recompile at all:
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;
}Token names are written unprefixed in Sass (). Bootstrap's dist and CDN CSS run PostCSS to add the prefix, so use when overriding the shipped CSS and unprefixed names when you compile the source yourself.
--primary-bg-subtle--bs---bs-*Runtime overrides are the right tool for per-page or per-tenant theming; compile-time config is for changing the system's defaults.
每个token都是CSS自定义属性,因此大多数颜色修改根本不需要重新编译:
css
/* 全局 — 如果在影子根中使用样式表,需要在 :host 上重复设置 */
:root,
:host {
--bs-primary-bg-subtle: #eef2ff;
}
/* 单个子树 */
.marketing-hero {
--bs-theme-bg-subtle: #eef2ff;
}Sass中的token名称是不带前缀的(如 )。Bootstrap的发布版和CDN CSS会通过PostCSS添加 前缀,因此覆盖官方发布的CSS时请使用 格式,如果你自己编译源码,则使用不带前缀的名称。
--primary-bg-subtle--bs---bs-*运行时覆盖适合用于单页面或多租户主题定制;编译时配置则用于修改系统的默认值。
Step 8: Functions and utilities
步骤8:函数与工具类
Helpers in for reading across the color maps, mostly used when generating utilities:
scss/_theme.scss- — flat map of color name to the raw value of that role.
theme-color-values($role) - — same, but as
theme-color-refs($role)references.var(--<name>-<role>) - — the equivalent for the layer color maps.
theme-token-refs($map, $prefix) - — an opacity ladder built with
theme-opacity-values($var, $fallback)againstcolor-mix().transparent
color-contrast($background)scss/_functions.scssvar()contrast$theme-colorsThe generated utilities follow the role names: , , , , , , , and , for every theme color. The layer colors get the same treatment ( through , through , ), and opacity is a numeric ladder on the same class names — , , , in steps of 10.
.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.fg-50.bg-70.border-30Reach for instead when you want a whole element themed rather than one property recolored.
.theme-*scss/_theme.scss- — 返回颜色名称到对应角色原始值的扁平映射。
theme-color-values($role) - — 同上,但返回的是
theme-color-refs($role)格式的引用。var(--<名称>-<角色>) - — 对应层级颜色映射的等效函数。
theme-token-refs($map, $prefix) - — 使用
theme-opacity-values($var, $fallback)和color-mix()混合生成的透明度阶梯。transparent
scss/_functions.scsscolor-contrast($background)var()$theme-colorscontrast生成的工具类遵循角色命名规则:每个主题色都对应 、、、、、、 和 等类。层级颜色也有对应的工具类( 到 、 到 、),同一类名还支持数值透明度阶梯——如 、、,步长为10。
.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.fg-50.bg-70.border-30如果你想要为整个元素设置主题,而不仅仅是修改单个属性的颜色,请使用 类。
.theme-*Step 9: Verify
步骤9:验证
- , then
npm run css-lint.npm run css - Grep the compiled for the tokens you expected (
dist/css/bootstrap.css,--bs-primary-bg-subtle) to confirm they were emitted.--bs-slate-500 - Check both color modes: OS preference, , and a nested
data-bs-theme="dark"inside it.data-bs-theme="light" - Verify contrast for any new theme color — at minimum on
contrast, andbgonfg, in both modes.bg-subtle - If you added or removed entries in or
$colors, confirm the generated utilities and$theme-colorsclasses changed accordingly, and that.theme-*still passes (the docs render swatches from these maps).npm run docs-build
- 先运行 ,再运行
npm run css-lint。npm run css - 在编译后的 中搜索你预期的token(如
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