カラーモード
Color modes
Bootstrapは、v5.3.0からカラーモード(テーマ)に対応しました。デフォルトのライトカラーモードと新しいダークカラーモード、またはテンプレートを使って独自のカラーモードを作成してください。
ダークモード
Bootstrapは、ダークモードを始めとするカラーモードをサポートするようになりました! v5.3.0では、独自のカラーモード・トグラーを実装することができ(Bootstrapのドキュメントにある例は下記を参照)、適切と思われるさまざまなカラーモードを適用することができます。ライトモード(デフォルト)とダークモードをサポートしています。カラーモードは、<html>
要素上でグローバルに切り替えることも、data-bs-theme
属性のおかげで、特定のコンポーネントや要素上で切り替えることもできます。
また、カラーモードミキシンのおかげで、メディアクエリの実装に切り替えることもできます。詳しくは使い方のセクションを参照してください。ただし、以下のようにコンポーネント単位でテーマを変更することはできません。
実例
例えば、ドロップダウンメニューのカラーモードを変更するには、親の.dropdown
にdata-bs-theme="light"
またはdata-bs-theme="dark"
を追加する。これで、グローバルカラーモードに関係なく、これらのドロップダウンメニューは指定したテーマの値で表示されるようになります。
<div class="dropdown" data-bs-theme="light">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButtonLight" data-bs-toggle="dropdown" aria-expanded="false">
Default dropdown
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButtonLight">
<li><a class="dropdown-item active" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Separated link</a></li>
</ul>
</div>
<div class="dropdown" data-bs-theme="dark">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButtonDark" data-bs-toggle="dropdown" aria-expanded="false">
Dark dropdown
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButtonDark">
<li><a class="dropdown-item active" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Separated link</a></li>
</ul>
</div>
仕組み
-
上で示したように、カラーモードのスタイルは
data-bs-theme
属性によって制御されます。この属性は<html>
要素に適用することも、他の要素やBootstrapコンポーネントに適用することもできます。もし<html>
要素に適用された場合、全ての要素に適用されます。コンポーネントや要素に適用された場合、その特定のコンポーネントや要素にスコープされます。 -
サポートしたいカラーモードごとに、共有のグローバルCSS変数に新しいオーバーライドを追加する必要があります。ダークモード用のスタイルシート
_root.scss
ではすでにこのようにしており、ライトモードがデフォルト値になっています。カラーモード固有のスタイルを記述するには、mixin CSSを使用します:// Color mode variables in _root.scss @include color-mode(dark) { // CSS variable overrides here... }
-
Bootstrapは、ダークモード用の共有グローバルCSS変数のオーバーライドに、カスタム
_variables-dark.scss
を使用しています。このファイルは独自のカラーモードには必要ありませんが、Bootstrapのダークモードには2つの理由で必要です。1つ目は、グローバルカラーをリセットする場所を1つにすることです。第二に、アコーディオンやフォームコンポーネントなどのCSSに埋め込まれた背景画像のために、いくつかのSass変数をオーバーライドする必要がありました。
例
ダークモードを有効にする
data-bs-theme="dark"
属性を<html>
要素に追加することで、プロジェクト全体で組み込みのダークカラーモードを有効にすることができます。これにより、特定のdata-bs-theme
属性が適用された要素以外のすべてのコンポーネントと要素にダークカラーモードが適用されます。クイックスタートテンプレートを基に作成されています:
<!doctype html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body>
<h1>Hello, world!</h1>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
</body>
</html>
Bootstrapにはまだビルトインのカラーモードピッカーが同梱されていませんが、私たちのドキュメントにあるものを使うことができます。詳しくはJavaScriptセクションをご覧ください
Sassで構築する
新しいダークモードオプションは、Bootstrapのすべてのユーザーが使用できますが、メディアクエリの代わりにデータ属性によって制御され、プロジェクトのカラーモードを自動的に切り替えることはできません。enable-dark-mode
をfalse
に変更することで、Sassを通してダークモードを完全に無効にすることができます。
カスタムSass mixinであるcolor-mode()
を使用することで、カラーモードを どのように 適用方法を制御することができます。デフォルトではdata
属性のアプローチを使用しており、訪問者が自動的なダークモードを選択したり、好みをコントロールできるような、よりユーザーフレンドリーなエクスペリエンスを作成することができます(こちらのドキュメントのように)。これはまた、異なるテーマや、ライトとダーク以外のカスタムカラーモードを追加するための簡単でスケーラブルな方法でもあります。
メディアクエリを使用し、カラーモードのみを自動化したい場合は、Sass変数を使ってmixinのデフォルトタイプを変更することができます。以下のスニペットとコンパイルされたCSS出力を見てみましょう。
$color-mode-type: data;
@include color-mode(dark) {
.element {
color: var(--bs-primary-text-emphasis);
background-color: var(--bs-primary-bg-subtle);
}
}
出力する:
[data-bs-theme=dark] .element {
color: var(--bs-primary-text-emphasis);
background-color: var(--bs-primary-bg-subtle);
}
そして、media-query
に設定する:
$color-mode-type: media-query;
@include color-mode(dark) {
.element {
color: var(--bs-primary-text-emphasis);
background-color: var(--bs-primary-bg-subtle);
}
}
出力する:
@media (prefers-color-scheme: dark) {
.element {
color: var(--bs-primary-text-emphasis);
background-color: var(--bs-primary-bg-subtle);
}
}
カスタムカラーモード
カラーモードの主な使用例はライトモードとダークモードですが、カスタムカラーモードも可能です。独自のdata-bs-theme
セレクタを作成し、カスタム値をカラーモードの名前として指定します。私たちは、Bootstrapのダークモード専用のSass変数を格納するために、_variables-dark.scss
スタイルシートを別に作成することにしましたが、これは必要ありません。
例えば、data-bs-theme="blue"
というセレクタで “blue theme"を作成することができます。カスタムSassまたはCSSファイルに新しいセレクタを追加し、必要に応じてグローバルまたはコンポーネントのCSS変数をオーバーライドします。Sassを使用している場合は、CSS変数のオーバーライドにSassの関数を使用することもできます。
[data-bs-theme="blue"] {
--bs-body-color: var(--bs-white);
--bs-body-color-rgb: #{to-rgb($white)};
--bs-body-bg: var(--bs-blue);
--bs-body-bg-rgb: #{to-rgb($blue)};
--bs-tertiary-bg: #{$blue-600};
.dropdown-menu {
--bs-dropdown-bg: #{mix($blue-500, $blue-600)};
--bs-dropdown-link-active-bg: #{$blue-700};
}
.btn-secondary {
--bs-btn-bg: #{mix($gray-600, $blue-400, .5)};
--bs-btn-border-color: #{rgba($white, .25)};
--bs-btn-hover-bg: #{darken(mix($gray-600, $blue-400, .5), 5%)};
--bs-btn-hover-border-color: #{rgba($white, .25)};
--bs-btn-active-bg: #{darken(mix($gray-600, $blue-400, .5), 10%)};
--bs-btn-active-border-color: #{rgba($white, .5)};
--bs-btn-focus-border-color: #{rgba($white, .5)};
--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(255, 255, 255, .2);
}
}
Some paragraph text to show how the blue theme might look with written copy.
<div data-bs-theme="blue">
...
</div>
JavaScript
訪問者やユーザーがカラーモードを切り替えられるようにするには、ルート要素である<html>
のdata-bs-theme
属性を制御するtoggle要素を作成する必要があります。このtogglerは、初期状態ではユーザーの現在のシステムカラーモードに従いますが、それを上書きして特定のカラーモードを選択するオプションを提供します。
ここでは、そのJavaScriptを見てみよう。私たち自身のコンポーネントのHTMLとCSSを使ってどのように実装されているか、私たち自身のドキュメントのナビバーを自由に調べてみてください。カラーモードにメディアクエリを使用する場合、暗黙的な制御を好むならJavaScriptを修正または削除する必要があるかもしれないことに注意してください。
/*!
* Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
*/
(() => {
'use strict'
const getStoredTheme = () => localStorage.getItem('theme')
const setStoredTheme = theme => localStorage.setItem('theme', theme)
const getPreferredTheme = () => {
const storedTheme = getStoredTheme()
if (storedTheme) {
return storedTheme
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
const setTheme = theme => {
if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-bs-theme', 'dark')
} else {
document.documentElement.setAttribute('data-bs-theme', theme)
}
}
setTheme(getPreferredTheme())
const showActiveTheme = (theme, focus = false) => {
const themeSwitcher = document.querySelector('#bd-theme')
if (!themeSwitcher) {
return
}
const themeSwitcherText = document.querySelector('#bd-theme-text')
const activeThemeIcon = document.querySelector('.theme-icon-active use')
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
element.classList.remove('active')
element.setAttribute('aria-pressed', 'false')
})
btnToActive.classList.add('active')
btnToActive.setAttribute('aria-pressed', 'true')
activeThemeIcon.setAttribute('href', svgOfActiveBtn)
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)
if (focus) {
themeSwitcher.focus()
}
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
const storedTheme = getStoredTheme()
if (storedTheme !== 'light' && storedTheme !== 'dark') {
setTheme(getPreferredTheme())
}
})
window.addEventListener('DOMContentLoaded', () => {
showActiveTheme(getPreferredTheme())
document.querySelectorAll('[data-bs-theme-value]')
.forEach(toggle => {
toggle.addEventListener('click', () => {
const theme = toggle.getAttribute('data-bs-theme-value')
setStoredTheme(theme)
setTheme(theme)
showActiveTheme(theme, true)
})
})
})
})()
テーマカラーを加える
アラートやリストグループのようないくつかのコンポーネントでは、$theme-colors
に新しい色を追加するだけでは不十分です。新しい色は、ライトテーマの$theme-colors-text
、$theme-colors-bg-subtle
、$theme-colors-border-subtle
でも定義する必要があります。ダークテーマの$theme-colors-text-dark
、$theme-colors-bg-subtle-dark
、$theme-colors-border-subtle-dark
でも定義する必要があります。
Sassは既存の変数やマップから独自のSass変数を生成することができないため、これは手作業となります。Bootstrapの将来のバージョンでは、重複を減らすためにこの設定を再検討します。
// Required
@import "functions";
@import "variables";
@import "variables-dark";
// Add a custom color to $theme-colors
$custom-colors: (
"custom-color": #712cf9
);
$theme-colors: map-merge($theme-colors, $custom-colors);
@import "maps";
@import "mixins";
@import "utilities";
// Add a custom color to new theme maps
// Light mode
$custom-colors-text: ("custom-color": #712cf9);
$custom-colors-bg-subtle: ("custom-color": #e1d2fe);
$custom-colors-border-subtle: ("custom-color": #bfa1fc);
$theme-colors-text: map-merge($theme-colors-text, $custom-colors-text);
$theme-colors-bg-subtle: map-merge($theme-colors-bg-subtle, $custom-colors-bg-subtle);
$theme-colors-border-subtle: map-merge($theme-colors-border-subtle, $custom-colors-border-subtle);
// Dark mode
$custom-colors-text-dark: ("custom-color": #e1d2f2);
$custom-colors-bg-subtle-dark: ("custom-color": #8951fa);
$custom-colors-border-subtle-dark: ("custom-color": #e1d2f2);
$theme-colors-text-dark: map-merge($theme-colors-text-dark, $custom-colors-text-dark);
$theme-colors-bg-subtle-dark: map-merge($theme-colors-bg-subtle-dark, $custom-colors-bg-subtle-dark);
$theme-colors-border-subtle-dark: map-merge($theme-colors-border-subtle-dark, $custom-colors-border-subtle-dark);
// Remainder of Bootstrap imports
@import "root";
@import "reboot";
// etc
CSS
変数
何十ものルートレベルのCSS変数が、ダークモードのオーバーライドとして繰り返されます。これらの変数はカラーモードセレクタにスコープされ、デフォルトでは data-bs-theme
に設定されていますが、prefers-color-scheme
メディアクエリを使用するように設定することもできます。これらの変数は、独自の新しいカラーモードを生成するためのガイドラインとして使用してください。
--#{$prefix}body-color: #{$body-color-dark};
--#{$prefix}body-color-rgb: #{to-rgb($body-color-dark)};
--#{$prefix}body-bg: #{$body-bg-dark};
--#{$prefix}body-bg-rgb: #{to-rgb($body-bg-dark)};
--#{$prefix}emphasis-color: #{$body-emphasis-color-dark};
--#{$prefix}emphasis-color-rgb: #{to-rgb($body-emphasis-color-dark)};
--#{$prefix}secondary-color: #{$body-secondary-color-dark};
--#{$prefix}secondary-color-rgb: #{to-rgb($body-secondary-color-dark)};
--#{$prefix}secondary-bg: #{$body-secondary-bg-dark};
--#{$prefix}secondary-bg-rgb: #{to-rgb($body-secondary-bg-dark)};
--#{$prefix}tertiary-color: #{$body-tertiary-color-dark};
--#{$prefix}tertiary-color-rgb: #{to-rgb($body-tertiary-color-dark)};
--#{$prefix}tertiary-bg: #{$body-tertiary-bg-dark};
--#{$prefix}tertiary-bg-rgb: #{to-rgb($body-tertiary-bg-dark)};
@each $color, $value in $theme-colors-text-dark {
--#{$prefix}#{$color}-text-emphasis: #{$value};
}
@each $color, $value in $theme-colors-bg-subtle-dark {
--#{$prefix}#{$color}-bg-subtle: #{$value};
}
@each $color, $value in $theme-colors-border-subtle-dark {
--#{$prefix}#{$color}-border-subtle: #{$value};
}
--#{$prefix}heading-color: #{$headings-color-dark};
--#{$prefix}link-color: #{$link-color-dark};
--#{$prefix}link-hover-color: #{$link-hover-color-dark};
--#{$prefix}link-color-rgb: #{to-rgb($link-color-dark)};
--#{$prefix}link-hover-color-rgb: #{to-rgb($link-hover-color-dark)};
--#{$prefix}code-color: #{$code-color-dark};
--#{$prefix}border-color: #{$border-color-dark};
--#{$prefix}border-color-translucent: #{$border-color-translucent-dark};
--#{$prefix}form-valid-color: #{$form-valid-color-dark};
--#{$prefix}form-valid-border-color: #{$form-valid-border-color-dark};
--#{$prefix}form-invalid-color: #{$form-invalid-color-dark};
--#{$prefix}form-invalid-border-color: #{$form-invalid-border-color-dark};
Sass変数
ダークカラーモード用のCSS変数は、部分的に_variables-dark.scss
内のダーク・モード固有のSass変数から生成されます。また、コンポーネント全体に使用されている埋め込みSVGの色を変更するためのカスタムオーバーライドも含まれています。
// scss-docs-start theme-text-dark-variables
$primary-text-emphasis-dark: tint-color($primary, 40%);
$secondary-text-emphasis-dark: tint-color($secondary, 40%);
$success-text-emphasis-dark: tint-color($success, 40%);
$info-text-emphasis-dark: tint-color($info, 40%);
$warning-text-emphasis-dark: tint-color($warning, 40%);
$danger-text-emphasis-dark: tint-color($danger, 40%);
$light-text-emphasis-dark: $gray-100;
$dark-text-emphasis-dark: $gray-300;
// scss-docs-end theme-text-dark-variables
// scss-docs-start theme-bg-subtle-dark-variables
$primary-bg-subtle-dark: shade-color($primary, 80%);
$secondary-bg-subtle-dark: shade-color($secondary, 80%);
$success-bg-subtle-dark: shade-color($success, 80%);
$info-bg-subtle-dark: shade-color($info, 80%);
$warning-bg-subtle-dark: shade-color($warning, 80%);
$danger-bg-subtle-dark: shade-color($danger, 80%);
$light-bg-subtle-dark: $gray-800;
$dark-bg-subtle-dark: mix($gray-800, $black);
// scss-docs-end theme-bg-subtle-dark-variables
// scss-docs-start theme-border-subtle-dark-variables
$primary-border-subtle-dark: shade-color($primary, 40%);
$secondary-border-subtle-dark: shade-color($secondary, 40%);
$success-border-subtle-dark: shade-color($success, 40%);
$info-border-subtle-dark: shade-color($info, 40%);
$warning-border-subtle-dark: shade-color($warning, 40%);
$danger-border-subtle-dark: shade-color($danger, 40%);
$light-border-subtle-dark: $gray-700;
$dark-border-subtle-dark: $gray-800;
// scss-docs-end theme-border-subtle-dark-variables
$body-color-dark: $gray-500;
$body-bg-dark: $gray-900;
$body-secondary-color-dark: rgba($body-color-dark, .75);
$body-secondary-bg-dark: $gray-800;
$body-tertiary-color-dark: rgba($body-color-dark, .5);
$body-tertiary-bg-dark: mix($gray-800, $gray-900, 50%);
$body-emphasis-color-dark: $white;
$border-color-dark: $gray-700;
$border-color-translucent-dark: rgba($white, .15);
$headings-color-dark: inherit;
$link-color-dark: tint-color($primary, 40%);
$link-hover-color-dark: shift-color($link-color-dark, -$link-shade-percentage);
$code-color-dark: tint-color($code-color, 40%);
//
// Forms
//
$form-select-indicator-color-dark: $body-color-dark;
$form-select-indicator-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='#{$form-select-indicator-color-dark}' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>");
$form-switch-color-dark: rgba($white, .25);
$form-switch-bg-image-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-color-dark}'/></svg>");
// scss-docs-start form-validation-colors-dark
$form-valid-color-dark: $green-300;
$form-valid-border-color-dark: $green-300;
$form-invalid-color-dark: $red-300;
$form-invalid-border-color-dark: $red-300;
// scss-docs-end form-validation-colors-dark
//
// Accordion
//
$accordion-icon-color-dark: $primary-text-emphasis-dark;
$accordion-icon-active-color-dark: $primary-text-emphasis-dark;
$accordion-button-icon-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/></svg>");
$accordion-button-active-icon-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-active-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/></svg>");
Sass mixins
ダークモード用のスタイルや、あなたが作成したカスタムカラーモードは、カスタマイズ可能なcolor-mode()
mixinを使ってdata-bs-theme
属性セレクタやメディアクエリに適切にスコープすることができます。詳細はSassの使い方を参照してください。
@mixin color-mode($mode: light, $root: false) {
@if $color-mode-type == "media-query" {
@if $root == true {
@media (prefers-color-scheme: $mode) {
:root {
@content;
}
}
} @else {
@media (prefers-color-scheme: $mode) {
@content;
}
}
} @else {
[data-bs-theme="#{$mode}"] {
@content;
}
}
}