Skip to main content Skip to docs navigation
Added in v5.1 GitHubで見る

CSSグリッド

CSS Grid

CSS Gridで構築された代替レイアウトシステムの有効化、使用方法、カスタマイズ方法について、サンプルとコードスニペットを交えてご紹介します。

Bootstrapのデフォルトのグリッドシステムは、10年以上にわたるCSSレイアウトテクニックの集大成です。しかし、新しいCSSグリッドのような、ブラウザで見られるようになったモダンなCSSの機能やテクニックの多くがない状態で作成されました。

注意:CSSグリッドシステムはv5.1.0から実験的なオプトイン方式になりました! デフォルトでは無効になっています。あなたのプロジェクトでこれを有効にする方法については、このまま読み進めてください。

仕組み

Bootstrap 5では、CSS GridをベースにBootstrapのひねりを加えた、独立したグリッドシステムを有効にするオプションが追加されました。レスポンシブなレイアウトを構築するために、思いつきで適用できるクラスはそのままですが、ボンネットの下では異なるアプローチを採用しています。

  • CSS Gridはオプトイン方式です。 $enable-grid-classes: falseを設定してデフォルトのグリッドシステムを無効にし、$enable-cssgrid: trueを設定してCSSグリッドを有効にします。その後、Sassを再コンパイルします。

  • .rowのインスタンスを.gridに置き換える。 .gridクラスはdisplay: gridを設定し、grid-templateを作成します。

  • .col-*クラスを.g-col-*クラスに置き換える これは、CSS Gridのカラムがwidthの代わりにgrid-columnプロパティを使用しているためです。

  • カラムとガターのサイズはCSS変数で設定する。 親である.gridにこれらを設定し、インラインまたはスタイルシートで--bs-columns--bs-gapを使って好きなようにカスタマイズします。

将来的には、gapプロパティがフレックスボックスをほぼ完全にブラウザでサポートするようになったため、Bootstrapはハイブリッドソリューションに移行することになるでしょう。

主な相違点

デフォルトのグリッドシステムとの比較:

  • フレックス・ユーティリティは、CSSグリッドのカラムには同じように影響しない。

  • ギャップはガターに代わるものです。gapプロパティはデフォルトのグリッドシステムの水平方向のpaddingを置き換え、よりmarginに近い働きをします。

  • そのため、.rowとは異なり、.gridは負のマージンを持ちません。また、マージンユーティリティを使用してグリッドのガターを変更することはできません。グリッドの隙間はデフォルトで水平方向と垂直方向に適用されます。詳細はカスタマイズセクションを参照してください。

  • インライン・スタイルとカスタム・スタイルは、モディファイア・クラスの代わりと考えるべきです(例えば、style="--bs-columns: 3;" vs class="row-cols-3"のように)。

  • ネストも同様に機能しますが、ネストされた.gridのインスタンスごとにカラム数をリセットする必要があるかもしれません。詳細はネスティングセクションを参照してください。

3列

.g-col-4クラスを使用すると、すべてのビューポートとデバイスで等幅の3列を作成できます。responsiveクラスを追加すると、ビューポートサイズによってレイアウトを変更できます。

.g-col-4
.g-col-4
.g-col-4
html
<div class="grid text-center">
  <div class="g-col-4">.g-col-4</div>
  <div class="g-col-4">.g-col-4</div>
  <div class="g-col-4">.g-col-4</div>
</div>

レスポンシブ

レスポンシブ・クラスを使用して、ビューポート間でレイアウトを調整します。ここでは、最も狭いビューポートでは2カラムから始め、ミディアムビューポート以上では3カラムに増やします。

.g-col-6 .g-col-md-4
.g-col-6 .g-col-md-4
.g-col-6 .g-col-md-4
html
<div class="grid text-center">
  <div class="g-col-6 g-col-md-4">.g-col-6 .g-col-md-4</div>
  <div class="g-col-6 g-col-md-4">.g-col-6 .g-col-md-4</div>
  <div class="g-col-6 g-col-md-4">.g-col-6 .g-col-md-4</div>
</div>

すべてのビューポートでこの2列レイアウトと比較してみてください。

.g-col-6
.g-col-6
html
<div class="grid text-center">
  <div class="g-col-6">.g-col-6</div>
  <div class="g-col-6">.g-col-6</div>
</div>

ラッピング

グリッドアイテムは水平方向にスペースがなくなると自動的に次の行に折り返されます。gapはグリッドアイテム間の水平方向と垂直方向の隙間に適用されることに注意してください。

.g-col-6
.g-col-6
.g-col-6
.g-col-6
html
<div class="grid text-center">
  <div class="g-col-6">.g-col-6</div>
  <div class="g-col-6">.g-col-6</div>

  <div class="g-col-6">.g-col-6</div>
  <div class="g-col-6">.g-col-6</div>
</div>

開始

開始クラスは、デフォルトのグリッドのオフセットクラスを置き換えることを目的としていますが、完全に同じというわけではありません。CSS Gridは、“この列で開始"と"この列で終了"をブラウザに指示するスタイルを通してグリッドテンプレートを作成します。これらのプロパティはgrid-column-startgrid-column-endです。開始クラスは前者の省略形です。カラムクラスと組み合わせることで、カラムのサイズや配置を自由に設定できます。開始クラスは1から始まります。

.g-col-3 .g-start-2
.g-col-4 .g-start-6
html
<div class="grid text-center">
  <div class="g-col-3 g-start-2">.g-col-3 .g-start-2</div>
  <div class="g-col-4 g-start-6">.g-col-4 .g-start-6</div>
</div>

自動列

グリッドアイテム(.gridの直接の子)にクラスがない場合、各グリッドアイテムのサイズは自動的に1列になります。

1
1
1
1
1
1
1
1
1
1
1
1
html
<div class="grid text-center">
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
</div>

この動作は、グリッド・カラム・クラスと混在させることができます。

.g-col-6
1
1
1
1
1
1
html
<div class="grid text-center">
  <div class="g-col-6">.g-col-6</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
</div>

ネスティング

デフォルトのグリッドシステムと同様に、CSSグリッドでは.gridを簡単に入れ子にすることができます。ただし、デフォルトとは異なり、このグリッドは行、列、ギャップの変更を継承します。下の例を見てください:

  • デフォルトの列数をローカルCSS変数で上書きする: --bs-columns: 3
  • 最初の自動カラムでは、カラム数は継承され、各カラムは利用可能な幅の3分の1になる。
  • 2つ目のオートカラムでは、ネストされた.gridのカラム数を12(デフォルト)にリセットしています。
  • 3つ目の自動カラムにはネストされたコンテンツがない。

実際には、デフォルトのグリッドシステムと比較して、より複雑なカスタムレイアウトが可能です。

First auto-column
Auto-column
Auto-column
Second auto-column
6 of 12
4 of 12
2 of 12
Third auto-column
html
<div class="grid text-center" style="--bs-columns: 3;">
  <div>
    First auto-column
    <div class="grid">
      <div>Auto-column</div>
      <div>Auto-column</div>
    </div>
  </div>
  <div>
    Second auto-column
    <div class="grid" style="--bs-columns: 12;">
      <div class="g-col-6">6 of 12</div>
      <div class="g-col-4">4 of 12</div>
      <div class="g-col-2">2 of 12</div>
    </div>
  </div>
  <div>Third auto-column</div>
</div>

カスタマイズ

ローカルCSS変数を使用して列数、行数、間隔幅をカスタマイズします。

Variable Fallback value Description
--bs-rows 1 グリッドテンプレートの行数
--bs-columns 12 グリッドテンプレートの列数
--bs-gap 1.5rem 列間の隙間の大きさ(垂直方向と水平方向)

これらのCSS変数はデフォルト値を持ちません。代わりに、ローカルインスタンスが提供される まで 使用されるフォールバック値を適用します。例えば、CSSグリッドの行に var(--bs-rows, 1)を使いますが、これは--bs-rowsを無視します。設定されると、.gridインスタンスはフォールバック値である1の代わりにその値を使用する。

グリッドクラスなし

.gridの直接の子要素はグリッド・アイテムなので、.g-colクラスを明示的に追加しなくてもサイズが調整されます。

Auto-column
Auto-column
Auto-column
html
<div class="grid text-center" style="--bs-columns: 3;">
  <div>Auto-column</div>
  <div>Auto-column</div>
  <div>Auto-column</div>
</div>

カラムとガター

列数とギャップを調整します。

.g-col-2
.g-col-2
html
<div class="grid text-center" style="--bs-columns: 4; --bs-gap: 5rem;">
  <div class="g-col-2">.g-col-2</div>
  <div class="g-col-2">.g-col-2</div>
</div>
.g-col-6
.g-col-4
html
<div class="grid text-center" style="--bs-columns: 10; --bs-gap: 1rem;">
  <div class="g-col-6">.g-col-6</div>
  <div class="g-col-4">.g-col-4</div>
</div>

行の追加

行を増やしたり、列の配置を変えたりします。:

Auto-column
Auto-column
Auto-column
html
<div class="grid text-center" style="--bs-rows: 3; --bs-columns: 3;">
  <div>Auto-column</div>
  <div class="g-start-2" style="grid-row: 2">Auto-column</div>
  <div class="g-start-3" style="grid-row: 3">Auto-column</div>
</div>

間隔

row-gapを修正することで縦方向の間隔を変更することができます。.gridにはgapを使いますが、row-gapcolumn-gapは必要に応じて修正できます。

.g-col-6
.g-col-6
.g-col-6
.g-col-6
html
<div class="grid text-center" style="row-gap: 0;">
  <div class="g-col-6">.g-col-6</div>
  <div class="g-col-6">.g-col-6</div>

  <div class="g-col-6">.g-col-6</div>
  <div class="g-col-6">.g-col-6</div>
</div>

そのため、垂直方向と水平方向に異なるgapを設定することができます。このgapは単一の値(すべての辺)または2つの値(垂直方向と水平方向)を取ることができます。これはgapのインラインスタイルか、CSS変数--bs-gapを使って適用することができます。

.g-col-6
.g-col-6
.g-col-6
.g-col-6
html
<div class="grid text-center" style="--bs-gap: .25rem 1rem;">
  <div class="g-col-6">.g-col-6</div>
  <div class="g-col-6">.g-col-6</div>

  <div class="g-col-6">.g-col-6</div>
  <div class="g-col-6">.g-col-6</div>
</div>

Sass

CSS Gridの制限事項の1つは、デフォルトのクラスが2つのSass変数、$grid-columns$grid-gutter-widthによって生成されることです。これは、コンパイルされたCSSで生成されるクラスの数を効果的に事前決定してしまいます。ここで2つのオプションがあります:

  • デフォルトのSass変数を変更し、CSSを再コンパイルします。
  • 提供されたクラスを補強するために、インラインまたはカスタム・スタイルを使用します。

例えば、カラム数を増やして間隔サイズを変更し、インラインスタイルと定義済みのCSS Gridカラムクラス(例:.g-col-4)を組み合わせて「カラム」のサイズを設定することができます。

14 columns
.g-col-4
html
<div class="grid text-center" style="--bs-columns: 18; --bs-gap: .5rem;">
  <div style="grid-column: span 14;">14 columns</div>
  <div class="g-col-4">.g-col-4</div>
</div>

` const jsSnippetContent = jsSnippet ? '\/\/ NOTICE!!! Initially embedded in our docs this JavaScript\n\/\/ file contains elements that can help you create reproducible\n\/\/ use cases in StackBlitz for instance\.\n\/\/ In a real project please adapt this content to your needs\.\n\/\/ \u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\u002b\n\n\/\*!\n \* JavaScript for Bootstrap\u0027s docs \(https:\/\/getbootstrap\.com\/\)\n \* Copyright 2011\-2023 The Bootstrap Authors\n \* Licensed under the Creative Commons Attribution 3\.0 Unported License\.\n \* For details, see https:\/\/creativecommons\.org\/licenses\/by\/3\.0\/\.\n \*\/\n\n\/\* global bootstrap: false \*\/\n\n\(\(\) =\u003e \{\n \u0027use strict\u0027\n\n \/\/ \-\-\-\-\-\-\-\-\n \/\/ Tooltips\n \/\/ \-\-\-\-\-\-\-\-\n \/\/ Instantiate all tooltips in a docs or StackBlitz\n document\.querySelectorAll\(\u0027\[data\-bs\-toggle=\u0022tooltip\u0022\]\u0027\)\n \.forEach\(tooltip =\u003e \{\n new bootstrap\.Tooltip\(tooltip\)\n \}\)\n\n \/\/ \-\-\-\-\-\-\-\-\n \/\/ Popovers\n \/\/ \-\-\-\-\-\-\-\-\n \/\/ Instantiate all popovers in docs or StackBlitz\n document\.querySelectorAll\(\u0027\[data\-bs\-toggle=\u0022popover\u0022\]\u0027\)\n \.forEach\(popover =\u003e \{\n new bootstrap\.Popover\(popover\)\n \}\)\n\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Toasts\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Used by \u0027Placement\u0027 example in docs or StackBlitz\n const toastPlacement = document\.getElementById\(\u0027toastPlacement\u0027\)\n if \(toastPlacement\) \{\n document\.getElementById\(\u0027selectToastPlacement\u0027\)\.addEventListener\(\u0027change\u0027, function \(\) \{\n if \(!toastPlacement\.dataset\.originalClass\) \{\n toastPlacement\.dataset\.originalClass = toastPlacement\.className\n \}\n\n toastPlacement\.className = `\$\{toastPlacement\.dataset\.originalClass\} \$\{this\.value\}`\n \}\)\n \}\n\n \/\/ Instantiate all toasts in docs pages only\n document\.querySelectorAll\(\u0027\.bd\-example \.toast\u0027\)\n \.forEach\(toastNode =\u003e \{\n const toast = new bootstrap\.Toast\(toastNode, \{\n autohide: false\n \}\)\n\n toast\.show\(\)\n \}\)\n\n \/\/ Instantiate all toasts in docs pages only\n \/\/ js\-docs\-start live\-toast\n const toastTrigger = document\.getElementById\(\u0027liveToastBtn\u0027\)\n const toastLiveExample = document\.getElementById\(\u0027liveToast\u0027\)\n\n if \(toastTrigger\) \{\n const toastBootstrap = bootstrap\.Toast\.getOrCreateInstance\(toastLiveExample\)\n toastTrigger\.addEventListener\(\u0027click\u0027, \(\) =\u003e \{\n toastBootstrap\.show\(\)\n \}\)\n \}\n \/\/ js\-docs\-end live\-toast\n\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Alerts\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Used in \u0027Show live alert\u0027 example in docs or StackBlitz\n\n \/\/ js\-docs\-start live\-alert\n const alertPlaceholder = document\.getElementById\(\u0027liveAlertPlaceholder\u0027\)\n const appendAlert = \(message, type\) =\u003e \{\n const wrapper = document\.createElement\(\u0027div\u0027\)\n wrapper\.innerHTML = \[\n `\u003cdiv class=\u0022alert alert\-\$\{type\} alert\-dismissible\u0022 role=\u0022alert\u0022\u003e`,\n ` \u003cdiv\u003e\$\{message\}\u003c\/div\u003e`,\n \u0027 \u003cbutton type=\u0022button\u0022 class=\u0022btn\-close\u0022 data\-bs\-dismiss=\u0022alert\u0022 aria\-label=\u0022Close\u0022\u003e\u003c\/button\u003e\u0027,\n \u0027\u003c\/div\u003e\u0027\n \]\.join\(\u0027\u0027\)\n\n alertPlaceholder\.append\(wrapper\)\n \}\n\n const alertTrigger = document\.getElementById\(\u0027liveAlertBtn\u0027\)\n if \(alertTrigger\) \{\n alertTrigger\.addEventListener\(\u0027click\u0027, \(\) =\u003e \{\n appendAlert\(\u0027Nice, you triggered this alert message!\u0027, \u0027success\u0027\)\n \}\)\n \}\n \/\/ js\-docs\-end live\-alert\n\n \/\/ \-\-\-\-\-\-\-\-\n \/\/ Carousels\n \/\/ \-\-\-\-\-\-\-\-\n \/\/ Instantiate all non\-autoplaying carousels in docs or StackBlitz\n document\.querySelectorAll\(\u0027\.carousel:not\(\[data\-bs\-ride=\u0022carousel\u0022\]\)\u0027\)\n \.forEach\(carousel =\u003e \{\n bootstrap\.Carousel\.getOrCreateInstance\(carousel\)\n \}\)\n\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Checks \u0026 Radios\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Indeterminate checkbox example in docs and StackBlitz\n document\.querySelectorAll\(\u0027\.bd\-example\-indeterminate \[type=\u0022checkbox\u0022\]\u0027\)\n \.forEach\(checkbox =\u003e \{\n if \(checkbox\.id\.includes\(\u0027Indeterminate\u0027\)\) \{\n checkbox\.indeterminate = true\n \}\n \}\)\n\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Links\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Disable empty links in docs examples only\n document\.querySelectorAll\(\u0027\.bd\-content \[href=\u0022#\u0022\]\u0027\)\n \.forEach\(link =\u003e \{\n link\.addEventListener\(\u0027click\u0027, event =\u003e \{\n event\.preventDefault\(\)\n \}\)\n \}\)\n\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Modal\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Modal \u0027Varying modal content\u0027 example in docs and StackBlitz\n \/\/ js\-docs\-start varying\-modal\-content\n const exampleModal = document\.getElementById\(\u0027exampleModal\u0027\)\n if \(exampleModal\) \{\n exampleModal\.addEventListener\(\u0027show\.bs\.modal\u0027, event =\u003e \{\n \/\/ Button that triggered the modal\n const button = event\.relatedTarget\n \/\/ Extract info from data\-bs\-\* attributes\n const recipient = button\.getAttribute\(\u0027data\-bs\-whatever\u0027\)\n \/\/ If necessary, you could initiate an Ajax request here\n \/\/ and then do the updating in a callback\.\n\n \/\/ Update the modal\u0027s content\.\n const modalTitle = exampleModal\.querySelector\(\u0027\.modal\-title\u0027\)\n const modalBodyInput = exampleModal\.querySelector\(\u0027\.modal\-body input\u0027\)\n\n modalTitle\.textContent = `New message to \$\{recipient\}`\n modalBodyInput\.value = recipient\n \}\)\n \}\n \/\/ js\-docs\-end varying\-modal\-content\n\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ Offcanvas\n \/\/ \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\n \/\/ \u0027Offcanvas components\u0027 example in docs only\n const myOffcanvas = document\.querySelectorAll\(\u0027\.bd\-example\-offcanvas \.offcanvas\u0027\)\n if \(myOffcanvas\) \{\n myOffcanvas\.forEach\(offcanvas =\u003e \{\n offcanvas\.addEventListener\(\u0027show\.bs\.offcanvas\u0027, event =\u003e \{\n event\.preventDefault\(\)\n \}, false\)\n \}\)\n \}\n\}\)\(\)\n' : null const project = { files: { 'index.html': markup, 'index.js': jsSnippetContent }, title: 'Bootstrap Example', description: `Official example from ${window.location.href}`, template: jsSnippet ? 'javascript' : 'html', tags: ['bootstrap'] } StackBlitzSDK.openProject(project, { openFile: 'index.html' }) }