Bootstrap4がリリースされてから約2年半になり、私自身も通常のWebサイトやWebアプリなどでよく使うようになりました。
基本的には指定のクラスをつけてわずかなJavascriptを書くだけで大抵のことは事足りますが、凝ったレイアウトや思い通りの挙動を実装するためにはちょっとしたコツや知識が必要です。
今回は私がBootstrap4を使う中で身につけた(というかググったというか試したというか…)、細かすぎるBootstrap4の小技を10個ご紹介します。
極力自前のスタイルは書かず、標準クラスで対応するようにし、Javascriptも必要最小限になるように意識しています。
目次
ADs
Bootstrap4ではtableをdiv.table-responsiveで囲うことでレスポンシブ対応となるのですが、これは親要素がoverflow:autoとなり狭いウインドウでは横スクロールして閲覧させるというものです。
1 2 3 4 5 6 |
<!-- 標準のレスポンシブ対応table --> <div class="table-responsive"> <table class="table"> ... </table> </div> |
大抵のケースではそれで問題ないですが、セルを組み替えてスクロールさせずに見せる方法です。
狭いウインドウのときは.row>.colのグリッドレイアウトとし、広いウインドウの場合はd-table-row/d-table-cellクラスによって通常のtableとして表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<table class="table"> <thead class="text-center"> <tr class="row mx-0 d-flex d-sm-table-row align-items-center"> <th class="col-1 d-block d-sm-table-cell align-middle">No.</th> <th class="col-11 d-block d-sm-table-cell align-middle">名前</th> <th class="col-4 d-block d-sm-table-cell align-middle">属性</th> <th class="col-4 d-block d-sm-table-cell align-middle">所属</th> <th class="col-4 d-block d-sm-table-cell align-middle">操作</th> </tr> </thead> <tbody> <tr class="row mx-0 d-flex d-sm-table-row align-items-center"> <td class="col-1 d-block d-sm-table-cell text-center align-middle">1</td> <td class="col-11 d-block d-sm-table-cell align-middle">あいうえお太郎</td> <td class="col-4 d-block d-sm-table-cell text-center align-middle">社畜</td> <td class="col-4 d-block d-sm-table-cell text-center align-middle">営業部</td> <td class="col-4 d-block d-sm-table-cell text-center align-middle"><button class="btn btn-primary" disabled>編集</button></td> </tr> <tr class="row mx-0 d-flex d-sm-table-row align-items-center"> <td class="col-1 d-block d-sm-table-cell text-center align-middle">1</td> <td class="col-11 d-block d-sm-table-cell align-middle">あいうえお太郎</td> <td class="col-4 d-block d-sm-table-cell text-center align-middle">社畜</td> <td class="col-4 d-block d-sm-table-cell text-center align-middle">営業部</td> <td class="col-4 d-block d-sm-table-cell text-center align-middle"><button class="btn btn-primary" disabled>編集</button></td> </tr> </tbody> </table> |
colを指定することでwidth:100%となってしまうため、width:autoとするスタイルが必要です。
borderは好みで指定してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
.table { th, td { width: auto !important; } @include media-breakpoint-down(xs) { td:nth-last-child(4)~td { border-top: none; } thead { tr { border-bottom: 2px solid $gray-300; } th { border-bottom: none; } } } } |
Bootstrap4の配色は標準では
primary
secondary
success
info
warning
danger
light
dark
の8色が用意されています。
しかしsuccess/info/danger/warningはアラートで使うものですので、有彩色では実質primaryとsecondaryしか使える色がありません。
Bootstrap4の色は$theme-colorsという配列で管理されています。
この配列に好きな色を追加することで、デフォルトの8色と同じくtext-xxx/bg-xxx/border-xxxのように使うことができます。
bootstrap.scssの中の@import “variables”;より後ろ、@import “mixins”;より前に追加してください。
1 2 3 4 5 6 7 8 |
@import "variables"; /* 色を足す @import "variables"の直後に書く */ $theme-colors: map-merge(('twitter': #53A7E8, 'facebook': #4064AD, 'tiktok': #F6305D), $theme-colors); @import "mixins"; |
Bootstrap4では文字サイズ調整用のクラスとしてdisplay-1~4が用意されています。
display-1~4は_type.scssというファイルで定義されていますので記述方法などを参考にしてみてください。
たとえば、display-5~7を足す場合は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/* 文字サイズを足す */ $display5-size: 2rem !default; $display6-size: 1.5rem !default; $display7-size: 1rem !default; $display5-weight: 300 !default; $display6-weight: 300 !default; $display7-weight: 300 !default; .display-5 { @include font-size($display5-size); font-weight: $display5-weight; line-height: $display-line-height; } .display-6 { @include font-size($display6-size); font-weight: $display6-weight; line-height: $display-line-height; } .display-7 { @include font-size($display7-size); font-weight: $display7-weight; line-height: $display-line-height; } |
Bootstrap4のborderクラスにはレスポンシブ対応のクラスが用意されておらず、「狭いウインドウならborder-top、広いウインドウならborder-right」ということができません(標準機能としてあってもよさそうですが)
下記を追加することで
border-sm //ウインドウサイズsm以上のときにborderがつく
border-sm-top //ウインドウサイズsm以上のときにborder-topがつく
border-sm-0 //ウインドウサイズsm以上のときにborderがなくなる
のように使うことができます。
@import “mixins”;より後ろ、@import “utilities”;より前のどこかに記述してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
@import "mixins"; /* @import "mixins"; より後ろ、@import "utilities";より前に書く*/ /*border-sm-top,border-md-0などを足す*/ $borders: top, right, bottom, left; @each $breakpoint in map-keys($grid-breakpoints) { @include media-breakpoint-up($breakpoint) { $infix: breakpoint-infix($breakpoint, $grid-breakpoints); .border#{$infix} { border: $border-width solid $border-color !important; } .border#{$infix}-0 { border: 0 !important; } @each $border in $borders { .border#{$infix}-#{$border} { border-#{$border}: $border-width solid $border-color !important; } .border#{$infix}-#{$border}-0.border#{$infix}-#{$border}-0 { border-#{$border}: 0 !important; } } } } |
Bootstrap4の標準クラスですが、Ver.4.2以降で使えるクラスなのでご存知ない方も多いかもしれません。
「m-n5/mt-sm-n3」のようにmargin用クラスにnをつけることでマイナス値のマージンが設定されます。
1 2 3 4 |
<div class="row align-items-center"> <div class="col bg-light border">あ<br>い<br>う<br>え<br>お</div> <div class="col border ml-n5 bg-primary text-white">このcolにネガティブマージンを設定している</div> </div> |
Bootstrap4のモーダルは1枚しか開けないようになっています。
Nested modals aren’t supported as we believe them to be poor user experiences.
Modal
「ネストされたモーダルはUXを損なうと思うのでサポートしていません」という意味でしょうか。
分からないでもないですが…多重にモーダルを開きたいときもあるでしょう。
モーダル本体のHTMLはbody直下にくるように書きます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<!-- モーダルを開くボタンは好きな位置に設置 --> <button class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">1枚目のモーダル</button> <!-- モーダル本体(body直下に書きます) --> <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">1枚目のモーダルです</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> モーダルの中からモーダルを開く<br><button class="btn btn-primary" data-toggle="modal" data-target="#exampleModal2">2枚目のモーダル</button> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> </div> </div> </div> </div> <div class="modal fade" id="exampleModal2" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">2枚目のモーダルです</h5><button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> これは2枚めのモーダル </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> </div> </div> </div> </div> |
data-toggle=”modal”を書いておけば多重でモーダルを開くことはできるのですが、モーダル本体と背景の黒いやつのz-indexが固定値なのでそこをJavascriptで調整します。
1 2 3 4 5 6 7 8 9 10 11 |
//モーダルの背景は999+モーダルの枚数、本体は1000+モーダルの枚数とすることでちゃんと順番どおりになる $('.modal').on('show.bs.modal', function (e) { $('.modal').each(function (key, value) { $(this).css('z-index', 1000 + key) $(this).on('transitionstart', function () { $('.modal-backdrop').each(function (key, value) { $(this).css('z-index', 999 + key) }) }) }) }) |
Collapseは標準では縦方向に開きますが、横方向に開かせる方法です。
Collapseはheightを0から要素の高さにアニメーションさせることで開閉を実現しているため、横方向にするためには
1.heightを固定(auto)にする
2.開閉のアニメーションをtransformX(-100%)→transformX(0)とする
の2点を実現させる必要があります。
まずHTMLについては、collapseをoverflow:hidden;の要素で囲います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<div class="row"> <div class="col-12 col-sm-auto mb-2 mb-sm-0"> <button class="btn btn-primary" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample"> クリックしたら開きます </button> </div> <div class="col-12 col-sm"> <div class="overflow-hidden"> <div id="collapseExample" class="collapse"> <div class="border bg-light p-3"> これはCollapseです。<br> これはCollapseです。<br> これはCollapseです。<br> これはCollapseです。 </div> </div> </div> </div> </div> |
ウインドウサイズsm以上のときは横に、以下のときは通常通り縦方向に、とする場合は以下のCSSを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* 横に開くCollapse */ @include media-breakpoint-up(sm) { #collapseExample { height: auto !important; display: block !important; transform: translateX(-100%); transition: 0.35s transform; &.show { transform: translateX(0); } } } |
ただしこの方法では横に開く場合でもheightを取得、設定する処理自体は発生するため、Collapseを開くタイミングがワンテンポ遅れます。この点を回避したい場合はソースを修正して再ビルドする必要があります。
1枚を開いたら他のCollapseを閉じる(つまりアコーディオン)動きについて、Bootstrap4のドキュメントでは.accordionクラスが必要とかcardコンポーネントでないと使えないような記述になっていますが、data-parent属性を足すだけで実現可能です。
親要素にIDを設定し、collapseには「data-parent=”親のID”」とすることでcollapseを開いたときに「自分以外を閉じる」という処理が追加されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<div class="row" id="collapseParent"> <div class="col-12 bg-light py-3 border" data-toggle="collapse" data-target="#collapseA" aria-expanded="false" aria-controls="collapseA">見出しA</div> <div class="col-12 collapse" data-parent="#collapseParent" id="collapseA"> <div class="p-3"> 見出しAをクリックしたらこれが開きます。 <br>見出しAをクリックしたらこれが開きます。 <br>見出しAをクリックしたらこれが開きます。 <br>見出しAをクリックしたらこれが開きます。 </div> </div> <div class="col-12 bg-light py-3 border" data-toggle="collapse" data-target="#collapseB" aria-expanded="false" aria-controls="collapseB">見出しB</div> <div class="col-12 collapse" data-parent="#collapseParent" id="collapseB"> <div class="p-3"> 見出しBをクリックしたらこれが開きます。 <br>見出しBをクリックしたらこれが開きます。 <br>見出しBをクリックしたらこれが開きます。 <br>見出しBをクリックしたらこれが開きます。 <br><br><br><br>見出しBをクリックしたらこれが開きます。 </div> </div> <div class="col-12 bg-light py-3 border" data-toggle="collapse" data-target="#collapseC" aria-expanded="false" aria-controls="collapseC">見出しC</div> <div class="col-12 collapse" data-parent="#collapseParent" id="collapseC"> <div class="p-3"> 見出しCをクリックしたらこれが開きます。 <br>見出しCをクリックしたらこれが開きます。 <br>見出しCをクリックしたらこれが開きます。 <br><br><br>見出しCをクリックしたらこれが開きます。 </div> </div> </div> |
tooltipを有効にする場合、属性としてdata-toggle=”tooltip”を足し、
1 |
$('[data-toggle="tooltip"]').tooltip() |
を実行する必要があります。
動的に追加される要素にもtooltipを使いたい場合、要素が追加されるたびにtooltip()を呼ぶ必要があるのですが、面倒くさいのでMutationObserverでDOMの変更を監視し、変更があったらtooltip()を呼ぶ方法です。
1 2 3 4 5 6 7 8 9 |
//動的に追加される要素でもtooltipを有効にする var target = $('body').get(0); var observer = new MutationObserver(function (records) { $('[data-toggle="tooltip"]').tooltip() }) observer.observe(target, { childList: true, subtree: true }); |
負荷を考えると必要なときだけtooltip()を実行するほうがいいと思いますが、手抜きをしたいときは試してみてください。
Popoverの内容を固定値ではなく、
1.Popoverを開くアクションを起こす(hoverやclickなど)
2.Popoverの内容を動的に生成(何かを計算したりAjaxで取得したり)
3.Popoverを表示
のように動的に生成する場合、表示位置の計算が内容の生成前に行われるため、Popoverの表示位置がずれたり表示時にガタついたりすることがあります。
初期表示はopacity:0にしておき、内容の生成が完了したらpopoverLoadedクラスを追加してopacity:1にするという方法です。
1 2 3 4 5 6 7 |
div.popover { opacity: 0 !important; } div.popover.popoverLoaded { opacity: 1 !important; } |
inserted.bs.popoverはpopover用のdivが挿入された直後に発生するイベントです。
表示時のイベントは
show.bs.popover→inserted.bs.popover→shown.bs.popover
の順番に発生します。
また、popoverのイベント内でthisはdata-toggle=”popover”が設定された要素(ボタンなど)であり、popover本体ではありません。
popover本体はaria-describedby属性の値がIDとなっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
//Popoverのcontentsを動的に生成した際に位置がずれるのを回避する $('[data-toggle="popover"]').on('inserted.bs.popover', function () { var $this = $(this) var id = $this.attr('aria-describedby'); //これがPopover本体のID //一旦表示されたPopoverは追加したクラスが残るので削除 $('#' + id).removeClass('popoverLoaded') }).on('shown.bs.popover', function () { var $this = $(this) var id = $this.attr('aria-describedby'); //これがPopover本体のID //たとえば、動的にコンテンツを追加しつつ親要素の色を取得してcontentsの文字色とする場合 var cls = $this.attr('class'); var clr = cls.match(/btn-(.+)/g); var clr = clr[0].replace('btn-', ''); $('#' + id).find('.popover-body').addClass('text-' + clr).html('この文字はdata-contentではなく動的に追加されています。'); //位置を設定し直す $(this).popover('update'); //表示完了クラスを追加 $('#' + id).addClass('popoverLoaded') }) |
Bootstrap4をより便利に使う小技やトラブル解決テクニックのご紹介でした。
Bootstrap5がリリースされたら役に立たない記事になってしまうかもしれませんが、それまでは誰かの役に立てば幸いです。
ADs
コメントはまだありません。