Rails で Bootstrap を使う gem「bootstrap-sass」を導入する
Rails アプリのレイアウト調整用に、bootstrap-sass
という gem を入れてみる。
はじめに : Sass とか Scss とか Less とか何なの
これらはいずれも、CSS の拡張言語。ピュアな CSS ではまだやりたくてもできない、変数宣言や入れ子ルールなどが実現できる。Sass やら Less やらは、それを実現する言語の種類の違い。
- Less : 「The Dynamic Stylesheet language」の略。Node.js パッケージでインストールすることが多い。
- Sass : 「Syntactically Awesome Style Sheets」の略。Ruby ベースなので gem でインストールする。
- Scss : Sass の表記法の1つ。元々の Sass がブレース
{}
を使わない記法だったりするのに対し、Scss はブレースを使うのでピュアな CSS っぽい見た目で書ける。
他にも Stylus とか、最近は PostCSS とか何かよー分からんモノも色々あるけど気にしない。
bootstrap-sass という gem
今回は、Rails で使うなら Ruby ベースで親和性の高い Sass がいいだろう、ってな理由で、Sass を使う bootstrap-sass という gem を選定した次第。記法としては昔ながらの Sass 記法ではなく、よりピュアな CSS に近い Scss 記法で記載する。この gem で導入できる Bootstrap は Ver. 3系である (古いバージョンを指定すれば Ver. 2系の使用も可)。
Ver. 4系の Bootstrap を入れたい場合は、bootstrap
という名前の gem が提供されている。インストール方法はこれから紹介する Ver. 3系とほとんど同じ模様。今後移行しやすいかも。ただ、現時点では Ver. 4系を急いで追っかけなくてもいいかなーという思いもあり、日本語の文献も多い Ver. 3系を選んだ。
- 参考 : GitHub - twbs/bootstrap-rubygem: Bootstrap 4 rubygem for Rails / Sprockets / Hanami / etc … 公式
- 参考 : 【Rails】Bootstrap 4(alpha)をインストール - Qiita
- 参考 : Ruby on Rails5アプリをBootstrap4デザインにする - Prog Space … View での指定方法のサンプルまでアリ
ちなみに、Less を用いる Bootstrap の gem もある。less-rails
・twitter-bootstrap-rails
という2つの gem を入れて使うようだ。Less には触れないので以下を参照。
- 参考 : Rails bootstrapの導入 sassのススメ - Qiita
- 参考 : 音速開発!RailsでBootstrapを導入する方法〜Less、Sass、Scss〜 | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
bootstrap-sass をインストールする
インストール方法は公式の README.md が丁寧に書いている。これを噛み砕いて説明していく。
bootstrap-sass をインストールしたい Rails アプリの Gemfile
に、以下を追記する。
gem 'sass-rails', '>= 3.2'
gem 'bootstrap-sass', '~> 3.3.6'
>=
はそのバージョン以上の最新をインストール。~>
はそのバージョン以上で、メインバージョンが上がらない範囲で最新をインストール、という書き方。
sass-rails
の方は、Rails アプリを new した時点で Gemfile
の上の方に既に書いてあるかもしれない。その場合は重複して書かないように。
Gemfile
を書き換えたら、この定義ファイルの内容に従って gem をインストールするため、bundle install
コマンドを打つ。
$ bundle install
…(中略)…
Using sass-rails 5.0.6
Installing bootstrap-sass 3.3.7
Installing autoprefixer-rails 6.7.7
…(中略)…
Bundle complete! 13 Gemfile dependencies, 58 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
とまぁこんな感じでインストールされる。
何やら勝手に autoprefixer-rails
もインストールされた。bootstrap-sass が依存しているためか、勝手にインストールされたのだろう。これも Gemfile
に書いておきたい便利 gem で、CSS でベンダプレフィックスをいちいち書かなくとも、Rails がコンパイル時に勝手にベンダプレフィックスを付与してくれるという gem なのだ。せっかくだから Gemfile
に明記しておいて、念のため再度 bundle install
しておこうか。
# Gemfile
# Autoprefixer Rails
gem 'autoprefixer-rails'
$ bundle install
Bundle complete! 14 Gemfile dependencies, 58 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
さっきので既に autoprefixer-rails
もインストールはされているので「58 gems now installed.
」の数字は変わらないが、Gemfile
に明記したので「13 Gemfile dependencies
」が「14 Gemfile dependencies
」に変わっている。
インストール自体はコレでいいのだが、Bootstrap の CSS (厳密には Scss ファイル) と JavaScript (jQuery 依存しているスクリプト部分) を、Rails を通して読み込ませてやるための初期設定が必要になる。
Scss の初期設定
Rails アプリ全体で読み込まれる CSS は、app/assets/stylesheets/application.css
というファイルに書くことになる。今回はコレを Scss 記法で書くため、ファイル名を application.scss
にリネームする (application.css.scss
としても OK)。
この中には、デフォルトでは以下のようなコメントが書かれている。
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/
このうち、
*= require_tree .
*= require_self
この *=
で始まる2行は、実はコメントではなく、Rails が特別に解釈して動作する実処理の行なのである。
アセット・パイプライン
これは、書いた順に指定したアセット (資産の意・この場合はスタイルシートファイル) を読み込んでくれる「アセット・パイプライン」という仕組みで、Rails はこの仕組を使って CSS と JS を勝手にコンパイル・結合してくれるのだ。ザックリ言ってしまえば、Rails が用意している Browserify・Gulp・Webpack 的な仕組み、といったところか。
この application.scss
と、後述する application.js
は、他のファイルを読み込んでアプリ全体に適用していくので、「マニフェストファイル」と呼ばれている。
require
というところから、まぁ何やら Import・Include 的なことをするのだなということは想像できると思う。具体的に tree
と self
が何をしているのかは以下のとおり。
*= require_tree .
… 対象のパスを示すため、ドット.
が付いている。つまり、このファイルがあるディレクトリ内のファイルを全部取ってきて読み込み結合してくれる (結合順序は保証しない)*= require_self
… そのファイルの内容をその指定の順番で出力する
「なんだ、色々読み込んでくれるなら便利なんじゃん?」と思うが、Scss を使う場合はこの require
を使ってはいけない。
- 参考 : Railsのマニフェストファイルを使ったJsとStylesheetの呼び出し - Qiita
- 参考 : Rails3.1から導入されたAsset Pipelineがよくわかってなかったから調べた - (゚∀゚)o彡 sasata299's blog
Scss を使うなら require
は使わない
sass-rails
と bootstrap-sass
を導入し、Scss を使う場合は、この require
を使わずに、@import
という Scss の書式でマニフェストファイルを書く必要が出てくる。これは公式のインストール方法としても記載されている。
Then, remove all the
*= require_self
and*= require_tree .
statements from the sass file. Instead, use@import
to import Sass files.Do not use
*= require
in Sass or your other stylesheets will not be able to access the Bootstrap mixins or variables.
require
を使っても、他の .scss
ファイルは正しく読み込んで結合してくれるのだが、変数やミックスインといった、Sass 独自の機能にアクセスできないという欠点がある (多分アセット・パイプラインは .scss
ファイルを個別にコンパイルし、最後に Concat するのだろう。これだと変数のスコープが保てないのだと推測できる)。つまり、Bootstrap (bootstrap-sass) が用意している変数を参照したりできないのである。
そのため、Scss の機能を生かして他のファイルを読み込ませるために @import
という記法を使うのである。
- Railsにbootstrap-sassを導入する - もはや芽は枯れた
-
//= require_tree
はどうするんだといえば、代わりに sass の@import
を利用する。 require で読み込んだら bootstrap のミックスインや変数にアクセスできない。
-
ではマニフェストファイルを書き換えよう
仕組みの話が長くなってしまったが、まずは先ほどの *= require
で始まる行を削除する。コメントアウトとして残しておくのであれば、「=
」を消して、* require_tree
といったコメントとして残しておくと良いだろう。
そして、Bootstrap を使うには以下の2行の @import
を書く。
// Bootstrap Sass
@import "bootstrap-sprockets";
@import "bootstrap";
必ず bootstrap-sprockets
の方を先に書く。
- 参考 : https://yet.unresolved.xyz/blog/2016/04/11/using-the-customized-bootstrap-in-rails/
-
ちなみに
bootstrap-sprockets
はフォントパスとかの書き換えをやってくれてる。
-
なお、Scss の中では通常の CSS では使えない、「//
」で始まる1行コメントが書ける。JavaScript チックなコメントも書けるというワケだ。この1行コメントはコンパイル時に削除されるので、コンパイル後も残したいコメントは「/*! コメント */
」と書くと良い。
全体としては、以下のように書き換えた。
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
* require は使わない
* require_tree .
* require_self
*/
// Bootstrap Sass
@import "bootstrap-sprockets";
@import "bootstrap";
require
と @import
と資産管理方法について
こうすると *= require_tree .
しないんだからコントローラごとの CSS が読み込めないじゃないか~どうしたらええねん~、となるが、みんな資産の管理方法は色々悩んでいるようである。
一見便利なアセット・パイプラインだが、実は色んな問題があって、「少なくとも *= require_tree .
は良くないよね」という流れになっている。
すなわち、配下の全ファイルを読み込むということは、無関係なコントローラ向けのスタイルも含んでいるし、その結合順序は保証されていないから、意図しないスタイルのカスケードが発生しうるということだ。ファイルサイズとしても重たくなるので、必要なページで必要なスタイルだけ読み込むべきだ、と。全ページに適用させるのは、こういう Bootstrap のような全体的なテーマだとか、Reset.css みたいなモノに限ろう、ということみたいである。
@import
で *= require_tree .
みたいなことがしたいのであれば、app/assets/stylesheets/partials/
というディレクトリを作り、application.scss
からは
@import "partials/*";
と書いて、配下の全ファイルを読み込ませることができる。
この辺は「こういうレールですよ!」という明確な決まりがないので、以下を参考にドウゾ。
- 参考 : Rails require_treeを排除し、アセットパイプラインで、コントローラー固有のCSS、JavaScriptを組み込む …
require_tree
を使わない管理方法3パターン。 - 参考 : rails なるべく簡単に bootstrap を使う方法を考えてみた - 日常 …
@import "partials/*";
の方法。 - 参考 : Railsでページごとのscssを管理する方法 -- blog.10rane.com … こちらも
partials
ディレクトリを作る方法。-
partialsディレクトリにファイルがないとエラーになる
-
- 参考 : css - Bootstrap Sass with Rails 4 - Stack Overflow … 「ぼくはこうやっているよ」という回答がいくつかある。
@import
を個別に書いているパターンとか。
JavaScript の初期設定
Scss の話が長くなってしまった。続いては Bootstrap が使用する JavaScript をマニフェスト・ファイルで読み込ませる。
app/assets/javascripts/application.js
を開くと、デフォルトでは以下のような状態になっていると思う。
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
先ほどの application.scss
と同様に、この application.js
の場合も「//= require_tree .
」という一見コメントに見える行が、アセット・パイプラインの設定をしている。
このデフォルトの記述だと、下から4行分が require をしていて、jQuery → jQuery ujs (Rails が使うライブラリ) → Turbolinks (画面遷移を Ajax で行い高速化を図る Rails が用意した仕組み) → tree .
すなわちその他のスクリプト、という順番で読み込んでいる。
Bootstrap の JS は jQuery を必要とするので、「//= require jquery
」よりも後の行に、以下の1行を追加する。
// Bootstrap Sass
//= require bootstrap-sprockets
この辺の読み込み順の関係は、静的な HTML で Bootstrap を読み込む場合の script 要素の登場順と同じことである。
なお、ここで読み込ませるのは //= require bootstrap
でも良い。違いは、Bootstrap のスクリプトファイルを個別に渡しているのが bootstrap-sprockets
で、結合した1ファイルを渡しているのが bootstrap
という違い。よく分からなければ上のままで。両方書いてはいけない。
bootstrap-sprockets
andbootstrap
should not both be included inapplication.js
.
bootstrap-sprockets
provides individual Bootstrap Javascript files (alert.js
ordropdown.js
, for example), whilebootstrap
provides a concatenated file containing all Bootstrap Javascripts.
初期設定完了!
長々と Rails でのアセット管理方法や仕組みについて絡めて書いてきたが、Rails アプリで Bootstrap を使うために必要なことを縮めると、以下にまとまる。
# Gemfile
gem 'sass-rails', '>= 3.2'
gem 'bootstrap-sass', '~> 3.3.6'
$ bundle install
// app/assets/stylesheets/application.scss
@import "bootstrap-sprockets";
@import "bootstrap";
// app/assets/javascripts/application.js
//= require jquery
//= require bootstrap-sprockets
これで Rails アプリの全ページに Bootstrap が適用されている。
試しに rails server
でサーバを起動し、適当なページを開いてみよう。Bootstrap のデフォルトスタイルが適用されていることが確認できると思う。
もう少し HTML 側で設定
全体の HTML を定義している app/views/layouts/application.html.erb
を開き、いくつか meta 要素を書いておこう。
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
Bootstrap の推奨テンプレートと同様に、ViewPort の設定とかをしておく。そういえば Rails の初期状態では charset 指定もないので追加しておいた。
あとは各 View の中で、各要素に Bootstrap の class を付与していけば Bootstrap デザインのできあがり。
<!-- たとえば一覧ページとかで… -->
<div class="container-fluid">
<div class="table-responsive">
<table class="table table-bordered table-hover">
<!-- 省略 -->
こんな感じでレスポンシブルなテーブルのできあがり!
その他参考
- 全部はいらないよね?bootstrap-sassをカスタマイズして使う方法 - Qiita … インストール方法とカスタマイズ方法、および
autoprefixer-rails
についても触れている。 - Railsにnode_modules以下のassetsを認識させる - Programming … RubyGem ではなく npm で bootstrap-sass を導入する方法。
- Railsで、任意のJavaScriptやCSSだけを読み込む - Qiita …
require
について色々。 - Rails 4のturbolinksについて最低でも知っておきたい事 | KRAY Inc … 途中で出てきた Turbolinks の弊害について。
- RailsのAsset Pipelineの理解とgemで管理しないJavaScriptライブラリの配置 | EasyRamble … サードパーティライブラリは
vendor/assets/
配下に入れて管理できる。 - Webサービスをスタートアップする10の手順(Rails編) - それはBooks … Rails アプリ作成時全般の Tips。Bootstrap は静的な資産を格納して使用するやり方。
- Rails jQueryを使用する – KeruuWeb … Rails にデフォルトで組み込まれる jQuery を使用し、外部ファイル化するまでの入門解説。
- Railsでvendor/assets/javascripts以下にあるファイルを特定のページでのみ使用する - Qiita … 特定ページで特定のスクリプトを読み込ませる