#329 More on Twitter Bootstrap pro
- Download:
- source codeProject Files in Zip (167 KB)
- mp4Full Size H.264 Video (35.7 MB)
- m4vSmaller H.264 Video (17.3 MB)
- webmFull Size VP8 Video (16.9 MB)
- ogvFull Size Theora Video (44.3 MB)
前回のエピソードでは、Twitter BootstrapをRailsで使用する方法を紹介しました。今回は、前回作成したプロジェクトにさらに機能を追加します。Simple Formを用いてフォームを改善する方法、LESSを用いてTwitter Bootstrapをカスタマイズする方法、SASSを利用したい場合の変更方法を紹介します。
ユーザ体験を改善する
前回作成したものを以下に示します。まずはこのアプリケーションのユーザ体験に関する問題にフォーカスします。
問題の1つ目は、フラッシュメッセージが表示されないという点です。編集フォームから商品情報を更新しても、更新されたことを知らせるフラッシュメッセージは表示されません。ドキュメントのcomponentsセクションを見ると、alertについてのセクションがあり、これがユーザに対してフラッシュメッセージを表示するのに役に立ちます。3種類の警告を表示するためのデフォルトのオプションは、success、information、warningです。更新メッセージを表示するためには、単にフラッシュメッセージをalert-success
というCSSクラスを持ったdiv
でラップします。
アプリケーションのレイアウトファイルにフラッシュメッセージを追加します。位置はcontainer
の中で、かつコンテンツの上です。
<div class="container"> <% flash.each do |name, msg| %> <div class="alert alert-<%= name == :notice ? "success" : "error" %>"> <%= msg %> </div> <% end %> <!-- Rest of content --> </div>
ここで複数のメッセージをループして、それぞれを表示します。各メッセージをdiv
でラップして、フラッシュメッセージの名前を使用してsuccessのアラートとerrorのアラートのどちらとして表示するかを決定します。商品情報を更新するとフラッシュメッセージが表示されるようになりました。
Twitter Bootstrapを使うと、コードを1行追加するだけでアラートに簡単に「閉じる」ボタンを追加できます。
<div class="container"> <% flash.each do |name, msg| %> <div class="alert alert-<%= name == :notice ? "success" : "error" %>"> <a class="close" data-dismiss="alert">x</a> <%= msg %> </div> <% end %> <!-- Rest of content --> </div>
商品情報を更新すると‘x’ボタンが表示され、クリックするとアラートが閉じられます。
この機能はJavaScriptによって処理されます。Bootstrapが提供するJavaScriptについてこれまであまり触れてきませんでしたが、便利なjQueryプラグインが多く含まれています。これらを使って、モーダルダイアログ、ドロップダウン、タブ、ツールチップ、ユーザがカーソルをホバーした時に情報を表示するポップオーバーなど、多くの部品を作成することができます。これらのプラグインはすべてすでに今回のRailsアプリケーションに含まれています。application.js
ファイルの中を見てみると、twitter/bootstrap
ファイルがインクルードされていて、これがすべてのプラグインをロードしています。bootstrap.js
というファイルもあり、これがプラグイン機能の一部を有効化しています。
jQuery -> $("a[rel=popover]").popover() $(".tooltip").tooltip() $("a[rel=tooltip]").tooltip()
データ検証
今回のRailsアプリケーションでもう一箇所ユーザ体験を改善できる部分は、フォームの特にデータ検証機能です。Product
モデルにはまだデータ検証機能を設定していないので、まずここから始めます。
class Product < ActiveRecord::Base validates_presence_of :name, :price end
商品情報を編集してフィールドの1つをブランクのままにすると、フォームに戻されますが何が悪かったかを示すエラーメッセージが表示されません。Twitter Bootstrapにはフォームにエラーメッセージを表示させる方法が含まれており、無効な入力が行なわれたフィールドに色をつけてくれるので、Product
フォームでこれを利用します。これの問題は、現状のままではフォームのマークアップがかなり複雑だということです。そこにデータ検証のロジックを組み込もうとしたら、ページはすぐに乱雑になってしまうでしょう。
<%= form_for @product, :html => { :class => 'form-horizontal' } do |f| %> <fieldset> <legend><%= controller.action_name.capitalize %> Product</legend> <div class="control-group"> <%= f.label :name, :class => 'control-label' %> <div class="controls"> <%= f.text_field :name, :class => 'text_field' %> </div> </div> <div class="control-group"> <%= f.label :price, :class => 'control-label' %> <div class="controls"> <%= f.text_field :price, :class => 'text_field' %> </div> </div> <div class="form-actions"> <%= f.submit nil, :class => 'btn btn-primary' %> <%= link_to 'Cancel', products_path, :class => 'btn' %> </div> </fieldset> <% end %>
そこでフォーム出力用のgemを利用することにします。SimpleFormは最近Bootstrapサポートを追加しました。Formtastic Bootstrap gemを使ってFormtasticを利用することもできますが、ここではSimpleFormを使ってみます。そのためにはgemfileにgemを追加してbundleコマンドを実行します。
gem 'simple_form'
次にSimpleFormのインストール用ジェネレータを実行します。そのときに、--bootstrap
オプションを指定してTwitter Bootstrap版が使用されるようにします。
$ rails g simple_form:install --bootstrap
これでSimpleFormを使ってフォームを修正できるようになりました。フォームの最初の部分でform_for
をsimple_form_for
に置き換え、SimpleFormのinputメソッドを使用して名称と価格の各フィールドを定義します。
<%= simple_form_for @product, :html => { :class => 'form-horizontal' } do |f| %> <fieldset> <legend><%= controller.action_name.capitalize %> Product</legend> <%= f.input :name %> <%= f.input :price %> <div class="form-actions"> <%= f.submit nil, :class => 'btn btn-primary' %> <%= link_to 'Cancel', products_path, :class => 'btn' %> </div> </fieldset> <% end %>
SimpleFormの仕組みがわからない場合は、エピソード234に詳しい説明があるので参照してください。では商品フォームを確認してみます。フォームをリロードして、名称を入力せずに商品情報を更新しようとすると、名称フィールドにエラーメッセージが表示されます。
スタイルをカスタマイズする
我々のアプリケーションは前よりもずっとよくなりましたが、さらにカスタマイズしてユニークなものにしたい場合はどうでしょうか? 例えばリンクやボタンの色やヘッダの外観を変えるにはどうすればいいでしょうか? ドキュメントのLESSを使用するのセクションを見ると、サイトの外観をカスタマイズするために変更できる変数のリストがあります。色やサイズなどを変更することが可能です。ただし、このページはすべての変数をリストアップしていません。すべてを見るためにはソースコードを確認する必要があります。
これらの変数はvariables.less
ファイルで定義されていて、そこにあるものの一部はドキュメントに記載されていません。これらの変数をbootstrap_and_overrides.css.less
ファイルの中で設定します。ここで気をつけなくてはいけないのは、最初にあるbootstrap
ファイルをインポートしている行の後で設定を行なうということです。iconSpritePath
とiconWhiteSpritePath
の2つの変数はこのファイルですでに設定されており、ファイルにはその他のいくつかの変数を設定するための説明があります。
@import "twitter/bootstrap/bootstrap"; body { padding-top: 60px; } @import "twitter/bootstrap/responsive"; // Set the correct sprite paths @iconSpritePath: asset-path('twitter/bootstrap/glyphicons-halflings.png'); @iconWhiteSpritePath: asset-path('twitter/bootstrap/glyphicons-halflings-white.png'); // Your custom LESS stylesheets goes here // // Since bootstrap was imported above you have access to its mixins which // you may use and inherit here // // If you'd like to override bootstrap's own variables, you can do so here as well // See http://twitter.github.com/bootstrap/less.html for their names and documentation // // Example: // @linkColor: #ff0000;
例として、ヘッダの色を少し明るくしたいとします。そのために以下のように変数を設定します。
@navbarBackground: #555; @navbarBackgroundHighlight: #888; @navbarText: #eee; @navbarLinkColor: #eee;
ここでサイトのページをリロードすると、ヘッダは明るい灰色になりました。
しかし、変数で簡単に変更できないものもあります。例えばヘッダ内のブランド名のテキストを設定したいとしましょう。この色を定義しているCSSはnavbar.less
ファイルの中にあり、このヘッダを定義しているbrand
クラスを見てみると、@white
変数の値に基づいた色が設定されていることがわかります。この変数の値を変更することもできますが、そうすることで希望しない他の部分に影響が出てしまいます。この1箇所の色だけを変更したいだけなので、変数を介しての操作は制限が多すぎます。しかしこれは大した問題ではありません。CSSに対して作業をおこなっているので、デフォルトのスタイルをbootstrap_and_overrides
でオーバーライドすることが可能です。
.navbar .brand { color: #FAFFB8; }
ブランド名のテキストは今は淡黄色ですが、あまりいいデザインではないので、思いついたスタイルで好きなようにオーバーライドしてみましょう。
何をインクルードするかをカスタマイズする
アプリケーションが出来上がるにつれて、Twitter Bootstrapの一部の部品を使用していないことに気づくかも知れません。そのような場合は、これらを削除してクライアントに送信されるコード量を減らした方がいいでしょう。Twitter Bootstrapのサイトには便利なページがあり、インクルードしたい部品を選んでカスタマイズ版をダウンロードすることが可能になっています。ただしこれによって静的ファイルがダウンロードされるのですが、今回はLESSを使っているので、これは我々が求めるものではありません。そうではなく、Railsアプリケーションにインポートされるファイルをカスタマイズするのがいいでしょう。bootstrap_and_overrides
ファイルはtwitter/bootstrap/bootstrap
をインポートしますが、そのインポートされたファイルのソースコードを見てみると、それがまた多数の他のファイルをインポートしていて、これを使ってどのファイルをインポートするかを決めることができます。
そのためには、bootstrap_and_overrides
の最初の行の@import "twitter/bootstrap/bootstrap";
を、このbootstrap.less
ファイルの内容と置き換えます。これはデフォルトでは同じ動作をしますが、これによってBootstrapのどの部品をインクルードするかを選択できるようになります。JavaScriptについても同じようなことが可能です。bootstrap.js
ファイルはBootstrapが提供するすべてのjQueryプラグインをrequireするので、application.js
ファイルで //=require twitter/bootstrap
の行をそのファイルの内容と置き換え、インクルードしたいものを選択します。
LESSの代わりにSASSを使用する
今回のエピソードを終わる前に、LESSの代わりにSASSを使いたい場合の設定方法を紹介します。LESSではなくSASSを選択する意味はどこにあるのでしょうか? Twitter Bootstrapのスタイルを大きく修正しようとする場合にはSASSを使うことを検討するべきで、その理由はless-railsとless-rails-bootstrapのgemの作者であるKen Collinsの最近のブログ記事に挙げられています。
asset pipelineによって、同じアプリケーション内でSASSとLESSの両方を使用することが可能です。例えばCSSで何か(今回修正したナビゲーションバーのブランド名など)をオーバーライドする場合、これを.css.scss
ファイルに移動できますが、必ずbootstrap_and_overrides
が先にロードされている必要があります。この方法の制限は、Twitter Bootstrapが使用する変数やmix-inとやりとりができないという点で、これはそれらがLESSのコードで定義されていることによります。
SASSを使用して変数とmix-inとやりとりしたい場合は、bootstrap-sass
gemを使用することを検討するべきです。これにはSASSで書かれたTwitter Bootstrapが含まれるため、変数をやり取りしたり、オーバーライドすることも可能です。アプリケーションで、LESSを使用するtwitter-bootstrap-rails
gemからbootstrap-sass
に切り替える方法を紹介します。まずgemfileの古いgemを置き換えて、再度bundle
コマンドを実行します。
gem 'bootstrap-sass'
次にbootstrap_and_overrides.css.less
ファイルの拡張子を.scss
に変更します。そしてファイルの中身を同じ内容の対応するSASSコードに置き換えます。
// Set the correct sprite paths $iconSpritePath: image-path('glyphicons-halflings.png'); $iconWhiteSpritePath: image-path('glyphicons-halflings-white.png'); $navbarBackground: #555; $navbarBackgroundHighlight: #888; $navbarText: #eee; $navbarLinkColor: #eee; @import "bootstrap"; body { padding-top: 60px; } @import "bootstrap-responsive"; .navbar .brand { color: #FAFFB8; }
ここでひとつ重要な違いは、bootstrap
をロードする前に変数を設定している点で、これはSASSとLESSの動作のしくみが異なることによります。ロードされたら、変更したいCSSを自由にオーバーライドできるようになります。
application.js
ファイルで、twitter/bootstrap
ではなくbootstrapをrequireします。前と同じように、特定のプラグインを選択してロードしたい場合には、各個別のファイルをばらばらにロードできます。bootstrap-sassのREADMEにはこのやり方の例があります。ここでアプリケーションをリロードすると、外観は前と変わりませんが、LESSではなくSASSが使われています。