跳到主要内容
输入关键词开始搜索,↑ ↓ 选择,Enter 打开
没有找到匹配的文档

主题

Bootstrap 主题是一组语义化命名的标记,用于为我们的组件、工具等进行样式设计。该主题是可配置的,可响应颜色模式,并且可以通过 Sass 或 CSS 使用。

它是如何工作的

主题颜色在 $theme-colors Sass map中定义。此映射用于生成我们的主题颜色值。你可以在 _theme.scss 文件中找到这些值。这些是我们为 Bootstrap 定义设计代币的地方,涵盖了明亮和暗色模式。

主题颜色包括以下语义颜色:

主题颜色默认值描述
primaryLoading...Loading... var(--bs-blue-500)主要操作的主要品牌颜色
accentLoading...Loading... var(--bs-indigo-500)互补品牌颜色选项
successLoading...Loading... var(--bs-green-500)积极的行动和成功的状态
dangerLoading...Loading... var(--bs-red-500)破坏性操作和错误状态
warningLoading...Loading... var(--bs-yellow-500)警告信息和状态
infoLoading...Loading... var(--bs-cyan-500)信息消息和中性状态
inverseLoading...Loading... var(--bs-gray-900)通过反转前景和背景来实现高对比度
secondaryLoading...Loading... var(--bs-gray-300)不那么显著的行为和状态

在每个语义主题色中,你会找到以下键,大多数键都是颜色模式自适应的:

主题令牌描述
base语义颜色的默认颜色值
fg可访问的文本颜色(针对正文,加上 subtle 和 muted 颜色标记)
fg-emphasis用于的强调文本颜色 muted 背景令牌
bg用于高对比度的纯色背景
bg-subtle最低对比度的背景,通常与 fg 文本颜色的键
bg-muted低对比度背景,常用于禁用状态
border边界和分隔线
focus-ring用于可见的焦点指示器和轮廓样式
contrast需要在上面可读的文字颜色 base 和 bg 颜色

令牌游乐场

每个组件都读取相同的主题和布局标记,因此一次更改会影响整个组。更改下面的半径、间距或主要颜色,观察按钮、输入框、警报和卡片如何一起更新。

半径
间隔物
主要的
重新铸造
一个令牌的变化会同时影响每个组件。
卡片标题

卡片

填充跟随间隔器,角落跟随半径。

CSS
.token-demo {
  --bs-radius-5: 0.5rem;
  --bs-spacer: 1rem;
  --bs-primary-base: var(--bs-blue-500);
  --bs-primary-bg: var(--bs-primary-base);
  --bs-primary-bg-subtle: light-dark(var(--bs-blue-100), var(--bs-blue-900));
  --bs-primary-fg: light-dark(var(--bs-blue-600), var(--bs-blue-400));
  --bs-primary-border: light-dark(var(--bs-blue-300), var(--bs-blue-600));
}

Remint 控件显示了该主题在今天的工作方式。将其设置为 All,每种颜色都会重新声明每个派生的令牌——bg-subtle、fg、border 以及其它——因此整个预览都会跟随变化。将其设置为 Base,则只有 --bs-primary-base 和 --bs-primary-bg 会改变。实心按钮会重新着色,但提醒仍保持编译好的蓝色配对,因为它的 bg-subtle、fg 和 border 令牌仍然指向 :root 上的蓝色调色板。

主题颜色

每一个 token 都可作为 CSS 变量使用,并且大多数随后被我们的工具和组件使用。因此,对于 primary 颜色,你有以下颜色:

主要的
基地
fg
前景强调
背景
背景-微妙
背景-静音
边界
焦点框
对比
口音
基地
fg
前景强调
背景
背景-微妙
背景-静音
边界
焦点框
对比
成功
基地
fg
前景强调
背景
背景-微妙
背景-静音
边界
焦点框
对比
危险
基地
fg
前景强调
背景
背景-微妙
背景-静音
边界
焦点框
对比
警告
基地
fg
前景强调
背景
背景-微妙
背景-静音
边界
焦点框
对比
信息
基地
fg
前景强调
背景
背景-微妙
背景-静音
边界
焦点框
对比
反向
基地
fg
前景强调
背景
背景-微妙
背景-静音
边界
焦点框
对比
次要
基地
fg
前景强调
背景
背景-微妙
背景-静音
边界
焦点框
对比

搭配

并非所有颜色都适用于所有用途,这取决于可访问性、颜色对比度以及整体美学考虑。以下是一些推荐的搭配。

  • contrast 与 bg 最匹配
  • fg 与 subtle 最匹配
  • fg-emphasis 与 muted 最匹配
  • border 与 subtle 最匹配,但也可以与 muted 一起使用
带主题颜色的示例元素
带主题颜色的示例元素
带主题颜色的示例元素
HTML
<div class="theme-primary vstack gap-3">
  <div style="color: var(--bs-theme-contrast); background: var(--bs-theme-bg);" class="p-3 rounded-5">
    Example element with theme color
  </div>
  <div style="color: var(--bs-theme-fg-emphasis); background: var(--bs-theme-bg-muted); border: 1px solid var(--bs-theme-border);" class="p-3 rounded-5">
    Example element with theme color
  </div>
  <div style="color: var(--bs-theme-fg); background: var(--bs-theme-bg-subtle); border: 1px solid var(--bs-theme-border);" class="p-3 rounded-5">
    Example element with theme color
  </div>
</div>

图层颜色

在 Bootstrap 中,用于前景色、背景色和边框色的颜色标记被称为 主题层颜色。由于这些层颜色有更细微的主题使用场景,它们在自己各自的 Sass map中进行配置,而不是在 $theme-colors Sass map中配置。

这三个主题的令牌在 $theme-fgs、$theme-bgs 和 $theme-borders Sass map中定义。这些映射用于生成颜色模式自适应的 color、background-color 和 border-color 值,然后这些值被我们的工具和组件使用。你可以在 _theme.scss 文件中找到这些值。

背景

主题背景包括多种实用和语义上的颜色选项。

背景色默认值描述
bodyLoading...Loading...默认背景颜色
secondaryLoading...Loading...最低对比度背景色
subtleLoading...Loading...低对比度背景色
mutedLoading...Loading...中等对比度的背景颜色,通常用于禁用状态
whiteLoading...Loading...纯白色背景
blackLoading...Loading...纯黑色背景
transparentLoading...Loading...透明背景颜色
inheritinherit继承的背景颜色

前景

几乎所有这些选项也适用于前景文本颜色。

前景色默认值描述
bodyLoading...Loading...默认前景色
secondaryLoading...Loading...最低对比度前景色
subtleLoading...Loading...低对比度前景色
mutedLoading...Loading...中等对比度前景色
whiteLoading...Loading...纯白色前景色
blackLoading...Loading...纯黑色前景色
inheritinherit继承的前景色

边界

边框颜色级别相似,但名称不同。

边框默认值描述
bgLoading...Loading...与主体背景颜色匹配的边框
bodyLoading...Loading...正文内容的默认边框颜色
mutedLoading...Loading...静音的,较低对比度的边框颜色,通常用于禁用状态
subtleLoading...Loading...微妙的、最低对比度的边框颜色
emphasizedLoading...Loading...强调的、更高对比度的边框颜色
whiteLoading...Loading...纯白色边框
blackLoading...Loading...纯黑色边框

示例

并非所有颜色都适用于所有用途,这取决于可访问性、颜色对比度以及整体美学考虑。以下是一些推荐的搭配。

  • fg-body 与所有 bg 颜色兼容
  • fg-1 与 bg-body、bg-1、bg-2 和 bg-3 兼容
  • fg-2 与 bg-body、bg-1 和 bg-2 兼容
  • fg-3 与 bg-body、bg-1 兼容

这里是一些展示它们在一起的例子。注意

fg-身体 在 bg-身体 上,带有 border-微妙
fg-body 在 bg-body 上
fg-3 在 bg-1 上
fg-2 在 bg-2 上
前景-1 在 背景-3 上
HTML
<div class="vstack gap-3">
  <div class="p-3 rounded-5 bg-body fg-body border border-subtle">
    fg-body on bg-body with border-subtle
  </div>
  <div class="p-3 rounded-5 bg-body fg-body border">
    fg-body on bg-body
  </div>
  <div class="p-3 rounded-5 bg-1 fg-3 border">
    fg-3 on bg-1
  </div>
  <div class="p-3 rounded-5 bg-2 fg-2 border">
    fg-2 on bg-2
  </div>
  <div class="p-3 rounded-5 bg-3 fg-1 border">
    fg-1 on bg-3
  </div>
</div>

颜色模式

Bootstrap 的主题和层颜色是 颜色模式自适应 多亏了我们使用 CSS light-dark() 功能。这让我们可以为一个组件同时指定两种颜色,一种用于浅色模式,一种用于深色模式。这些颜色可以通过使用 data-bs-theme 要设置的属性 color-scheme 属性到 light 或者 dark.

默认情况下,color-scheme: light dark 设置在 :root 元素上,这意味着 Bootstrap 会遵循用户的系统偏好。你可以通过在任何元素上设置 data-bs-theme="light" 或 data-bs-theme="dark" 来在任何层级上覆盖此设置,从而强制对子树使用特定模式。根据元素的不同,你可能需要包含 .bg-body、.fg-body 或类似的工具类以确保颜色应用正确。

这是同一组组件在浅色模式和深色模式下并排显示的效果。请注意背景中使用了 .bg-body。如果没有它,浅色模式演示将不会有白色背景——只是浅色模式的组件显示在深色背景上。

[!代码 高亮]
浅色模式
卡片标题

一些快速的示例文本,用于扩展卡片标题并构成卡片内容的大部分。

这是一个主要警报。

[!代码 高亮]
深色模式
卡片标题

一些快速的示例文本,用于扩展卡片标题并构成卡片内容的大部分。

这是一个主要警报。

HTML
<div class="row g-0">
  <div class="md:col-6 vstack gap-3 p-4 bg-body fg-body" data-bs-theme="light">
    <h6 class="fw-semibold">Light mode</h6>
    <div class="card">
      <div class="card-body">
        <h5 class="card-title">Card title</h5>
        <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card’s content.</p>
      </div>
    </div>
    <div class="alert theme-primary"><p>This is a primary alert.</p></div>
    <input type="text" class="form-control" placeholder="Form control">
    <div class="form-field">
      <input type="checkbox" id="checkLabel" class="check" />
      <label for="checkLabel">Example new checkbox</label>
    </div>
    <div class="vstack gap-2">
      <button type="button" class="btn-solid theme-primary">Primary</button>
      <button type="button" class="btn-subtle theme-secondary">Secondary</button>
    </div>
  </div>
  <div class="md:col-6 vstack gap-3 p-4 bg-body fg-body" data-bs-theme="dark">
    <h6 class="fw-semibold">Dark mode</h6>
    <div class="card">
      <div class="card-body">
        <h5 class="card-title">Card title</h5>
        <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card’s content.</p>
      </div>
    </div>
    <div class="alert theme-primary"><p>This is a primary alert.</p></div>
    <input type="text" class="form-control" placeholder="Form control">
    <div class="form-field">
      <input type="checkbox" id="checkDarkLabel" class="check" />
      <label for="checkDarkLabel">Example new checkbox</label>
    </div>
    <div class="vstack gap-2">
      <button type="button" class="btn-solid theme-primary">Primary</button>
      <button type="button" class="btn-subtle theme-secondary">Secondary</button>
    </div>
  </div>
</div>

在底层,像 --bs-primary-fg 这样的令牌值会根据当前的颜色模式的不同而解析不同。例如,在我们的 _theme.scss 中,主要文本颜色定义为:

SCSS
          "fg": light-dark(var(--blue-600), var(--blue-400)),
        

当 data-bs-theme="light" 处于活动状态(或用户的系统偏好为浅色)时,它解析为 var(--blue-600)。在深色模式下,它解析为 var(--blue-400)——一种在深色背景下仍保持可读性的较浅色调。同样的模式适用于背景、边框以及所有其他自适应标记。

有关如何全局切换颜色模式、构建自定义模式以及 JavaScript 切换示例的更多详细信息,请参阅 颜色模式文档。

主题工具类

我们从$theme-colors Sass map生成主题工具类类,使所有主题颜色令牌可作为 CSS 变量使用。我们在组件变体中使用这些变量,以便通过单个全局类快速进行主题化。这要求组件支持主题颜色,但并非每个组件都支持。

使用主题工具类,你可以通过一个类将主题颜色应用到元素上。

主要警报

主要徽章 主要微妙徽章
HTML
<div class="alert theme-primary"><p>Primary alert</p></div>
<div>
  <button type="button" class="btn-solid theme-primary">Primary button</button>
  <button type="button" class="btn-outline theme-primary">Primary outline button</button>
  <button type="button" class="btn-subtle theme-primary">Primary subtle button</button>
  <button type="button" class="btn-text theme-primary">Primary text button</button>
</div>
<div>
  <span class="badge theme-primary">Primary badge</span>
  <span class="badge badge-subtle theme-primary">Primary subtle badge</span>
</div>

你可以将主题颜色工具类应用于容器,任何支持主题的子元素都将继承该主题颜色。

[!代码 高亮]

主要警报

主要徽章 主要微妙徽章
HTML
<div class="vstack gap-3 theme-primary">
  <div class="alert"><p>Primary alert</p></div>
  <div>
    <button type="button" class="btn-solid">Primary button</button>
    <button type="button" class="btn-outline">Primary outline button</button>
    <button type="button" class="btn-subtle">Primary subtle button</button>
    <button type="button" class="btn-text">Primary text button</button>
  </div>
  <div>
    <span class="badge">Primary badge</span>
    <span class="badge badge-subtle">Primary subtle badge</span>
  </div>
</div>

这也意味着你可以在特定组件上用另一个主题颜色覆盖容器的主题颜色。

主要警报

[!代码 高亮] [!代码 高亮]
成功徽章 [!代码 高亮] 主要微妙徽章
HTML
<div class="vstack gap-3 theme-primary">
  <div class="alert"><p>Primary alert</p></div>
  <div>
    <button type="button" class="btn-solid theme-inverse">Inverse button</button>
    <button type="button" class="btn-outline">Primary outline button</button>
    <button type="button" class="btn-subtle theme-danger">Danger subtle button</button>
    <button type="button" class="btn-text">Primary text button</button>
  </div>
  <div>
    <span class="badge theme-success">Success badge</span>
    <span class="badge badge-subtle">Primary subtle badge</span>
  </div>
</div>

重置

在嵌套容器上使用 .theme-reset 可以停止继承那些令牌。然后,支持主题的子组件将再次使用它们的组件默认值。

[!代码 高亮]

主要警报

主要徽章
[!代码 高亮]

默认警报

默认徽章
HTML
<div class="vstack gap-3 theme-primary">
  <div class="alert"><p>Primary alert</p></div>
  <div>
    <button type="button" class="btn-solid">Primary button</button>
    <span class="badge">Primary badge</span>
  </div>

  <div class="vstack gap-3 theme-reset">
    <div class="alert"><p>Default alert</p></div>
    <div>
      <button type="button" class="btn-solid">Default button</button>
      <span class="badge">Default badge</span>
    </div>
  </div>
</div>

该类将每个 --theme-* 自定义属性设置为 initial。这会使属性无效,因此 var(--theme-bg, fallback) 使用回退值。在此不要使用 unset——unset 会再次从父元素继承。

主题 Sass map

我们使用一个大型的嵌套 Sass map来生成我们的主题颜色值。

$theme-colors: ();
// stylelint-disable-next-line scss/dollar-variable-default
$theme-colors: defaults(
  (
    "primary": (
      "base": var(--blue-500),
      "fg": light-dark(var(--blue-600), var(--blue-400)),
      "fg-emphasis": light-dark(var(--blue-800), var(--blue-200)),
      "bg": var(--blue-500),
      "bg-subtle": light-dark(var(--blue-100), var(--blue-900)),
      "bg-muted": light-dark(var(--blue-200), var(--blue-800)),
      "border": light-dark(var(--blue-300), var(--blue-600)),
      "focus-ring": light-dark(color-mix(in oklch, var(--blue-500) 50%, var(--bg-body)), color-mix(in oklch, var(--blue-500) 75%, var(--bg-body))),
      "contrast": var(--white)
    ),
    "accent": (
      "base": var(--indigo-500),
      "fg": light-dark(var(--indigo-600), color-mix(in oklch, var(--indigo-400), var(--indigo-300))),
      "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)
    ),
    "success": (
      "base": var(--green-500),
      "fg": light-dark(var(--green-600), var(--green-400)),
      "fg-emphasis": light-dark(var(--green-800), var(--green-300)),
      "bg": var(--green-500),
      "bg-subtle": light-dark(var(--green-100), var(--green-900)),
      "bg-muted": light-dark(var(--green-200), var(--green-800)),
      "border": light-dark(var(--green-300), var(--green-600)),
      "focus-ring": light-dark(color-mix(in oklch, var(--green-500) 50%, var(--bg-body)), color-mix(in oklch, var(--green-500) 75%, var(--bg-body))),
      "contrast": var(--white)
    ),
    "danger": (
      "base": var(--red-500),
      "fg": light-dark(var(--red-600), var(--red-400)),
      "fg-emphasis": light-dark(var(--red-800), var(--red-300)),
      "bg": var(--red-500),
      "bg-subtle": light-dark(var(--red-100), var(--red-900)),
      "bg-muted": light-dark(var(--red-200), var(--red-800)),
      "border": light-dark(var(--red-300), var(--red-600)),
      "focus-ring": light-dark(color-mix(in oklch, var(--red-500) 50%, var(--bg-body)), color-mix(in oklch, var(--red-500) 75%, var(--bg-body))),
      "contrast": var(--white)
    ),
    "warning": (
      "base": var(--yellow-500),
      "fg": light-dark(var(--yellow-700), var(--yellow-400)),
      "fg-emphasis": light-dark(var(--yellow-800), var(--yellow-300)),
      "bg": var(--yellow-500),
      "bg-subtle": light-dark(var(--yellow-100), var(--yellow-900)),
      "bg-muted": light-dark(var(--yellow-200), var(--yellow-800)),
      "border": light-dark(var(--yellow-300), var(--yellow-600)),
      "focus-ring": light-dark(color-mix(in oklch, var(--yellow-500) 50%, var(--bg-body)), color-mix(in oklch, var(--yellow-400) 85%, var(--bg-body))),
      "contrast": var(--gray-900)
    ),
    "info": (
      "base": var(--cyan-500),
      "fg": light-dark(var(--cyan-600), var(--cyan-400)),
      "fg-emphasis": light-dark(var(--cyan-800), var(--cyan-300)),
      "bg": var(--cyan-500),
      "bg-subtle": light-dark(var(--cyan-100), var(--cyan-900)),
      "bg-muted": light-dark(var(--cyan-200), var(--cyan-800)),
      "border": light-dark(var(--cyan-300), var(--cyan-600)),
      "focus-ring": light-dark(color-mix(in oklch, var(--cyan-500) 50%, var(--bg-body)), color-mix(in oklch, var(--cyan-500) 75%, var(--bg-body))),
      "contrast": var(--gray-900)
    ),
    "inverse": (
      "base": var(--gray-900),
      "fg": light-dark(var(--gray-900), var(--gray-200)),
      "fg-emphasis": light-dark(var(--gray-975), var(--white)),
      "bg": light-dark(var(--gray-900), var(--gray-025)),
      "bg-subtle": light-dark(var(--gray-100), var(--gray-900)),
      "bg-muted": light-dark(var(--gray-200), var(--gray-300)),
      "border": light-dark(var(--gray-400), var(--gray-100)),
      "focus-ring": color-mix(in oklch, light-dark(var(--gray-900), var(--gray-100)) 50%, var(--bg-body)),
      "contrast": light-dark(var(--white), var(--gray-900))
    ),
    "secondary": (
      "base": var(--gray-200),
      "fg": light-dark(var(--gray-600), var(--gray-400)),
      "fg-emphasis": light-dark(var(--gray-800), var(--gray-200)),
      "bg": light-dark(var(--gray-100), var(--gray-600)),
      "bg-subtle": light-dark(var(--gray-050), var(--gray-800)),
      "bg-muted": light-dark(var(--gray-100), var(--gray-700)),
      "border": light-dark(var(--gray-300), var(--gray-600)),
      "focus-ring": color-mix(in oklch, light-dark(var(--gray-500), var(--gray-300)) 50%, var(--bg-body)),
      "contrast": light-dark(var(--gray-900), var(--white))
    )
  ),
  $theme-colors
);

自定义地图

配置 $theme-colors 通过主要入口点与 @use ... with (). 我们的 defaults() 函数将你的映射合并到内置映射之上,因此标准主题保持不变,你只添加所需的内容。层映射($theme-bgs, $theme-fgs,和 $theme-borders) 以相同的方式工作。

SCSS
          @use "../node_modules/bootstrap/scss/bootstrap" with (
  $theme-colors: (
    // Add a new theme color
    "brand": (
      "base": var(--indigo-500),
      "bg": var(--indigo-500),
      "contrast": var(--white)
    ),
    // Remove a built-in theme color
    "info": null
  )
);
        

每个主题颜色都是一个嵌套映射,因此合并是单层的。要更改内置主题的某个子键,请传递该主题的整个子映射。有关更多详细信息,请参见 Sass 自定义文档。

CSS 变量

CSS 变量是从 $theme-colors Sass map在 :root 内部水平 _root.scss 使用 Sass 循环。

// Generate semantic theme colors
@each $color-name, $color-map in $theme-colors {
  @each $key, $value in $color-map {
    $root-tokens: map.set($root-tokens, --#{$color-name}-#{$key}, $value);
  }
}

// Generate background tokens
@each $key, $value in $theme-bgs {
  $root-tokens: map.set($root-tokens, --bg-#{$key}, $value);
}

// Generate foreground tokens
@each $key, $value in $theme-fgs {
  $root-tokens: map.set($root-tokens, --fg-#{$key}, $value);
}

// Generate border tokens
@each $key, $value in $theme-borders {
  $root-tokens: map.set($root-tokens, --border-#{$key}, $value);
}