軽くbootstrapvueを使っているため、覚書を残しておきます(vuetifyもだいたい同じです)。bootstrapの記事を何記事も書きたくないため、この記事に全部まとめています。
(追記)あまりに長くなったためモバイル対応だけ別記事にしました。
公式サイトをみると大抵のことは丁寧に書いてくれています(英語)が、デフォルト値などが邪魔になることやbootstrapを使わない方がよいケースもあるため、実践で気付いたことを含めてまとめです。
Contents
- 1 【使い方】nuxtでbootstrapvueのレイアウト
- 2 bootstrapのmargin/paddingが邪魔だから削除したい
- 3 bootstrapvueのinput要素など
- 3.1 ラジオボタン(radio button)のクリックイベント(click event)
- 3.2 ラジオボタン(radio button)でcssサイズ変更が効かない罠
- 3.3 画像をアップロードできるb-form-fileよりVeeValidate
- 3.4 input要素の横並び
- 3.5 b-input-groupのレスポンシブ対応
- 3.6 b-input-groupの横と縦の中央あわせ
- 3.7 フォームの横並び
- 3.8 bootstrapvueを使わないfor文の横並び
- 3.9 テキストとセレクトボックスの高さを揃える
- 3.10 タブの実装
- 3.11 タブの幅widthをフル幅にする
- 3.12 b-cardの背景とborderをシンプルにnone
- 3.13 card-bodyのpaddingが邪魔
- 3.14 チェックボックスの判定
- 3.15 b-form-inputは使える?
- 3.16 トグルボタンは?
- 3.17 モダールウィンドウ
- 3.18 画像の横並び
- 3.19 アコーディオン
- 3.20 プロフィール
- 3.21 ナビ(b-navbar)の文字色が変わらない!?
- 3.22 ナビ(b-navbar)の表示(d-block)・非表示(d-none)
- 3.23 bootstrapvueのナビの右寄せ
- 3.24 レスポンシブテーブル(b-table)
- 3.25 b-tableにfontawesomeを表示する
- 4 bootstrap-vueの不具合・エラー
【使い方】nuxtでbootstrapvueのレイアウト
b-containerの使い方
まず、コンテンツ部分はb-containerで囲みます。
<b-container fluid="sm">
狭い
</b-container>
<b-container fluid="md">
やや狭い
</b-container>
<b-container fluid="lg">
やや広い
</b-container>
<b-container fluid="xl">
広い
</b-container>
b-containerはxlが好みです。
b-containerをフル幅にする
xlでも1カラムの場合、短く左右が余ってしまいます。その場合は指定を削るだけでよさそうです。
<b-container fluid>
フル幅
</b-container>
Using the
https://bootstrap-vue.org/docs/components/layoutfluid
prop on<b-container>
will render a container that is always 100% width, regardless of viewport breakpoint.
bootstrapのmargin/paddingが邪魔だから削除したい
個人的なやり方なので参考程度にしてください。
nuxtのdefault.vueはとにかく0にする。下層に影響してごっちゃになります。。
b-rowにmargin、b-colにpaddingが入っています。
調整する際に塗りつぶすとわかりやすいです。
<template>
<div>
<HeaderMenu />
<b-row class="mx-0">
<b-col lg="9" class="px-0">
<div class="white-bg">
<nuxt />
</div>
</b-col>
<b-col lg="3">
<Sidebar />
</b-col>
</b-row>
<Footer />
</div>
</template>
しかし、これだけではまとまりません。各ページに入っているb-containerのpaddingも0にします。
<b-container fluid="xl" class="px-0">
</b-container>
最初、適当に作っているときに軽いノリで画像など要素の方をあわせていたのですが調整に時間がかかることが発覚して途中で軌道修正しました。大元を調整することにより、以下の調整は不要になる場合もあります。
結局、個人開発していて思ったのは、bootstrapそのものを外した方がよかったかもしれません。ただ、かろうじてレイアウトのみ残しました。個人的には結構デザインを思い通りにいじりたくなるので、ピュアなCSSで書いた方が楽だった気がします。端から端まで塗りつぶしなどを多用しないレイアウトならそんなに気にならないのかもしれませんが。
デザインにあまりこだわりがない人はbootstrapを使ってもいいと思いますが、最終的にデザインにこだわりたい人は、そのうちbootstrapが邪魔になるのでbootstrapは必要最低限にした方がよさそうです。
b-container fluidのpaddingが邪魔
b-containerは左右に15pxずつpaddingが入っています。たとえば、アイキャッチ画像のようなものを目一杯広げたいときに邪魔になることがあります。
通常はpaddingが入っていて問題ないため、no paddingするのではなく、画像を広げたい場所だけ次のコードで対応を行いました。右にはみでるため、marginで綺麗に中央にもってきました。
.photo-img {
margin: 0 -15px;
width: calc(100% + 30px);
}
b-rowとb-colのレイアウト崩れ
bootstrapは合計12にしておけばレイアウトは崩れにくいのですが、なんかb-rowとb-colの間にdivを入れると、b-colが効いていないようですね。前後に入れましょう。
<b-row class="my-2 py-2"> <div> <b-col cols="12"> </b-col> </div> </b-row>
mx-0の罠
.row { display: flex; flex-wrap: wrap; margin-right: -15px; margin-left: -15px; }
mx-0にすると、デフォルトのマージン-15pxがなくなり、たとえば、背景色を塗りつぶした場合、端から端まで埋まらないことが起こります。
b-rowは使わずdivなどで背景色を隅から隅まで塗りたい場合は次のような対応が必要です。
<div class="bg" style="margin: 0 -15px;"></div>
b-col忘れに注意
b-rowの下にうっかりhタグなどを書いてしまってもeslintのエラーはでません。しかし、もともとあった15pxのmarginなどが効いていません。b-rowとb-colは一緒に使いましょう。1ピクセルのこだわりをしだすと後から修正することになります。
また、b-colにclass名を追加すると、b-colが元から持っているパラメーターが影響してレイアウトがうまく揃わないことがあります。中にdivをいれる方が無難かもしれません。
mx-5以上にする
このあたりが中途半端に感じてしまうのですが、、bootstrapはなぜか5以上できないっぽいです。。結局、styleで調整しました。-15のpaddingが入っていることもあり、mx-5が15*5で75pxに調整(調整方法により異なるかもです)。
<b-row class="py-2" style="margin: 0 5rem 0 5rem;"><b-row>
my-1で謎の余白ができる
background-colorを指定いる場合ですが、b-rowと次の要素の間に謎の白い線が入って困りました。うっかりmy-0をmy-1としていたためです。。ただそれだけです。
レイアウトの横並び
<b-row class="my-2 py-2 line"> <b-col cols="2"> </b-col> <b-col cols="10"> </b-col> </b-row>
レイアウトは線を入れることが多いでしょう。
.line { border-bottom: 1px solid #f2f2f2; }
b-rowの横並びと中央あわせ
表示要素の中央あわせはどうするか。
(追記)もっと簡単な方法がありました。親要素以下、中央になります。
<b-row class="text-center"></b-row>
CSSを確認すると以下のようになっています。
.text-center { text-align: center !important; }
旧記事。
<b-col cols="12" align-content="center"> </b-col>
ただ、これじゃうまくいかない場合があります。
中央合わせと横並びをあわせて行いたい場合は、親要素にflexが手っ取り早いです。
.wrap { display: flex; justify-content: center; }
他にも子要素にdisplay: inline-block、親要素にtext-align:centerなんていう方法もありますが、詳細は割愛しますが、for文など入りコードが複雑になった場合、flexの方があっさりと解決できると思ったことがあります。
b-rowで高さを揃える
stackoverflowに以下のアドバイスがありました。
https://stackoverflow.com/questions/61505624/bootstrapvue-best-way-to-vertically-align-content
しかし、個人的にはこれではやりたいことができず、bootstrapに元からあるrow-eq-heightは効かないです。
結局、入れ子にしたdivのclassで高さを揃えました。
<b-row>
<b-col>
<div style="height: 250px;">
</div>
</b-col>
</b-row>
わかりやすくするためにstyleで書いていますが、実際はclassです。
bootstrapvueでサイドバーをわける
nuxtのレイアウト機能、具体的にはlayouts/default.vueですが、default.vue内でb-colを使うと、簡単にサイドバーをわけることができます。
bootstrapvueのinput要素など
clickはボタンなのでinputはchangeを使いましょう。v-on:change=@change省略記法です。
<b-form-radio v-on:click="event">動かない</b-form-radio> <b-form-radio v-on:change="event">動く</b-form-radio> <b-form-radio @change="event">動く</b-form-radio>
beforeでボーダーを使ってボタンを表示し、通常のボタンはopacity: 0%;していますね。通常のやり方でラジオボタンのサイズなどを変えようとしても効きませんでした。
いろいろなカスタマイズする方法はありますが、元に戻す方法は以下のとおりです。
.custom-control-label::before { border: none; } .custom-control-input { width: 5vw; height: 5vw; opacity: 100%; }
こちらチェック時のコードも修正が必要ですね。
もしくはborderの方をそのままいかすかですかね。今回は後者の方がコストが安そうだったので選択しました。
.custom-control-label::before { position: static; width: 5vw; height: 5vw; /* border: none; */ }
bootstrapって余計なことしていることが多く、こういうこと調べているとbootstrap使わなくてもいいんじゃ…と思ってしまうのですよね。。
画像をアップロードできるb-form-fileよりVeeValidate
画像をアップロードできるb-form-fileという機能があります。
<b-form-file id="img" v-model="img" placeholder="" drop-placeholder="" accept=".jpg, .png" required plain ></b-form-file>
b-form-fileでも画像ファイルの種類ぐらいは制御できるのですが、画像サイズや縦横のピクセル数まで制御できるVeeValidateに魅力を感じ使っていません。
input要素の横並び
b-input-groupなら同列になることがわかりました。
https://stackoverflow.com/questions/27451693/display-two-fields-side-by-side-in-a-bootstrap-form
結構、他でも使えるかも。
https://getbootstrap.jp/docs/4.2/components/input-group/
b-input-groupは基本input要素に使うもののようです。たとえばセレクトボックスの誕生日の入力とかチェックボックスの羅列です。
b-input-groupのレスポンシブ対応
b-colとかは使いません。不都合が構造になることが多くて・・・。
公式にはresponsiveのことが書かれていませんでした。結局、一般的なCSSの対応をしました。
@media (max-width: 768px) { .input-group { display: block; } }
たとえば、横並びのチェックボックスが縦になります。
参考。
https://stackoverflow.com/questions/22138708/how-to-make-input-group-responsive-search-and-dropdown
ただ、input-groupの場合、他に影響がでることが多いため実際は別クラスの対応が多いですね。
@media (max-width: 768px) { .responsive-input-group { display: block; } }
b-input-groupの横と縦の中央あわせ
b-input-groupはソースコードをみるとflexになっています。
中央あわせする場合は次のとおりです。
<b-input-group style="justify-content: center;" > </b-input-group>
justify-content: space-between;は両端のアイテムを余白を空けずに配置し、他の要素は均等に配置します。単純に均等の場合はjustify-content: space-around;ですね。
<b-input-group style="justify-content: space-between;" > </b-input-group>
高さはalign-items: center;。上揃えの場合はalign-items: start;、下揃えの場合はalign-items: end;などで注意しましょう。うっかりtopと書いたことがある。
フォームの横並び
<b-form inline></b-form>
スマホでinlineが効かず困ったことがあります。768px必要だと。bootstrapの仕様ですが、bootstrapvueもおそらく一緒でしょう。これは使えません。。
Add .form-inline to your form (which doesn’t have to be a
https://getbootstrap.com/docs/3.4/css/
bootstrapvueを使わないfor文の横並び
bootstrapvueを使わず切り抜けたいときがあります。
この方法はわりと使うため覚書として残しておきます。forと部分はspanにしないと横並びになりません。
<span v-for="l in list" :key="l.key">
<div style="display: inline-block;">
<div class="name">{{ l.name }}</div>
<div class="price">
<span>{{ l.price }}</span>
</div>
</div>
</span>
テキストとセレクトボックスの高さを揃える
<b-col cols="3" style="display: flex; align-items: center;"> {{ animal.key }} <b-col cols="9"> <b-form-select v-model="model" :options="options" ></b-form-select> </b-col>
テキストが一行ならline-height: 2.2;もありです。
タブの実装
https://bootstrap-vue.org/docs/components/tabs
<template> <div> <b-container fluid="xl"> <b-card no-body> <p>タブを選んでください。</p> <b-tabs card> <b-tab title="タブ1" active><p>タブ1</p></b-tab> <b-tab title="タブ2"><p>タブ2</p></b-tab> <b-tab title="タブ3"><p>タブ3</p></b-tab> </b-tabs> </b-card> </b-container> </div> </template>
cardは使わなくてもいいですが、使った方がレイアウトしやすいかもしれません。
タブの幅widthをフル幅にする
fillをつけるだけです。ui的に押しやすいかもです。
<b-tabs fill></b-tabs>
b-cardの背景とborderをシンプルにnone
よく邪魔になることがある。この書き方がシンプル。
<b-card class="bg-transparent border-0"></b-card>
card-bodyのpaddingが邪魔
@media (max-width: 480px) { .card-body { padding: 0 !important; } }
card-bodyというクラスにpaddingが入っていました。モバイルなどで邪魔になることがあるのですよね…。
チェックボックスの判定
v-modelで簡単にできます。
<div v-for="task in tasks"> <b-form-checkbox v-model="task.checked"> </b-form-checkbox> </div>
firebaseからデータを取得し、checkedというプロパティがない場合も勝手に作ってくれます。
b-form-inputは使える?
focus時に青色のoutlineなどがつきます。使っていたのですけど、結局自分で色などを選びたくなって外しました。input系は開発を進めると使わなくなるケースが多いですね。
トグルボタンは?
トグルボタンはいろいろデザインの工夫もできます。
bootstrapvueもちょっとありましたが、個人的には普通にCSSのコードで書いた方がよいという結論です。詳しくはこちらの記事をみてください。
モダールウィンドウ
bootstrapvueにはモーダルウィンドウの機能はあります。
ただ、柔軟性に欠け構造的に問題がでそうだったので、Udemyで紹介されていたモーダルウィンドウの方法を採用しました。
【Vue.js2&Vue.js3対応】基礎から【Vuetify】を使った応用まで! 超初心者から最短距離でレベルアップ
という講座です。詳しくはこちらの記事をみてください。
https://bootstrap-vue.org/docs/components/modal
画像の横並び
https://bootstrap-vue.org/docs/components/image
アコーディオン
accordionはbootstrapの機能を使わせてもらいました。最小レベルのコードは以下のような感じ。
<b-button v-b-toggle.accordion-1 block>アコーディオン1</b-button>
<b-collapse id="accordion-1" visible>
中身
</b-collapse>
accordionはトグルの一種でidでひっかけてボタンを押しているだけです。
blockはブロック要素にする。visibleはデフォルト時に開いた状態にします。
公式のリファレンスはこちら。
https://bootstrap-vue.org/docs/components/collapse
v-forでまわす場合は次のようになります。
<div v-for="(l, index) in list" :key="index">
<b-button v-b-toggle="'accordion-' + index" block>
{{ l.name }}
</b-button>
<b-collapse :id="'accordion-' + index">中身</b-collapse>
</div>
プロフィール
Avatarという機能があるんですね。いつか使ってみたいです。
https://bootstrap-vue.org/docs/components/avatar
bootstrapはヘッダーにえいっと文字色を指定しても変わらないようです。。個別に上書きする方法にしました。
.navbar-dark .navbar-toggler {
color: rgba(255, 255, 255, 0.5);
border-color: rgba(255, 255, 255, 0.1);
}
.navbar-dark .navbar-nav .nav-link {
color: rgba(255, 255, 255, 0.5);
border-color: rgba(255, 255, 255, 0.1);
}
darkかlightかのどちらかが指定されていることが多いはずです。
このほかにもpaddingなどの弊害も多いです。
ナビは表示したり非表示にしたりが多いです。
d-blockは表示、d-noneは非表示です。
基本はd-noneで消せばいいだけです。ただ、PCだけ表示したい場合は全部消して表示するみたいな書き方になるようです。
この機能はbootstrapのものです。
<div class="d-md-none">
モバイルだけ表示する要素
</div>
<div class="d-none d-lg-block">
PCだけ表示する要素
</div>
bootstrapvueのナビの右寄せ
ml-auto(margin autoみたいな感じなのでlとrが逆)です。けど、レスポンシブのメニュー内にいれない中央あわせと右寄せはposition: absoluteの方が楽かもしれません。その場合はハンバーガーメニューのアイコンを使って高さの調整が必要になるかもしれません。
absoluteの弊害としてはtop:50%にするとハンバーガーメニューが開いたとき、開いた中央にきてしまいましたね。。
レスポンシブテーブル(b-table)
スマホになると左右2列の縦並びになる方式を採用しました。htmlは簡単です。
<b-table stacked="md" striped hover :items="items"></b-table>
thead-class="bg-primary text-white"
htmlに上記のコードをつかえばヘッド部分に色をつけられますが、全体として思った通りにならずfieldsで色をつけています。
scriptはこうです。
export default { data() { return { items: [ { 項目: 'A', 名前: 'Aさん', 年齢: '29' }, { 項目: 'B', 名前: 'Bくん', 年齢: '31' }, ], fields: [ { key: '項目', class: 'bTableStyle' }, { key: '名前', variant: 'danger' }, { key: '年齢', thClass: 'bg-white text-dark' } ] } } }
ただし、variantは列を塗れますが、任意の色がつけられません。thClassもあまり融通がききません。
左側と最初の一行目に色をつけたい場合、次のような感じがいいかもしれません。
{ key: '項目', tdClass: 'bTableLeftCellStyle', thStyle: 'background-color: #f2f2f2;' }, { key: '名前', thStyle: 'background-color: #f2f2f2;' }, { key: '年齢', thStyle: 'background-color: #f2f2f2;' }
色を自分で選びたい場合は、thClassよりthStyleがよいですかね。ちなみに、tdStyleはないようです。classとtdClassはここでは効果がかわりません。
classはcssの適応が必要です。
::v-deep .table .bTableLeftCellStyle { background-color: #323232; }
CSSはtext-alignを左寄せと右寄せで配置したい場合、ちょっとややこしかったですけど、結論としてはこうです。
@media (max-width: 767.98px) { ::v-deep .table.b-table.b-table-stacked-md > tbody > tr > [data-label]::before { text-align: left; } ::v-deep .table.b-table.b-table-stacked-md > tbody > tr > [data-label] > div { text-align: right; } }
簡単に解説すると、左側はdata-labelでbeforeの要素を使っているため、beforeが最後につきます。
右側も下記のようなコードではうまくいきません。
.table.b-table.b-table-stacked-md > tbody > tr > td > div { text-align: right; }
.table > tbody > tr > td > div { text-align: right; }
どちらも::v-deepは必須です。::v-deepはscopedのままdeep selectors。スタイルをオーバライドできるようです。
ただ、stylelintのルールにひっかるため回避のコードが必要です。
module.exports = { rules: { 'selector-pseudo-element-no-unknown': [ true, { ignorePseudoElements: ['v-deep'] } ] } };
bootstrapってなんか回りくどいですね。。テーブルは楽になっているかわかりません。。
b-tableにfontawesomeを表示する
b-tableにfontawesomeを表示する方法です。○×など普通に入力してもいいのですけど、線の太さなどの問題があり美しくなかったりします。そこでアイコンを使おうというわけです。
最近、簡単に書けるコードはTwitterでつぶやくことにしました。よければFollow Me!
昔はslot-scopeを使っていたようですが、非推奨になったため上記のように書くようです。
公式の記載はこちらです。
https://bootstrap-vue.org/docs/components/table#custom-data-rendering
bootstrap-vueの不具合・エラー
CSSが全般的に崩れる
ある日、突然、すべてのCSSが崩れる状態になったことがあった。直近の作業を見なしていくとよくみるとbootstrapに絡んだコードばかりだった。
bootstrapのバージョンを5にしたのが原因だった。(注)bootstrapvueではなく、bootstrap。
ひとまず、4.6にダウングレードしたら元に戻りました。
コメント