読者です 読者をやめる 読者になる 読者になる

望月いちろうのREADME.md

書き溜めておいた技術記事や旅行記のバックアップです。

Bootstrap 入門 | かんたんリスポンシブサイト構築

Webアプリケーションの開発者を悩ませる大きな問題の一つがUIです。

それは、単純に画面の色感やフォントのタイプやサイズのバランスといって基本的なデザインの問題に始まり、特にデバイスやOSごとに異なる画面幅、解像度への対応の問題はそのバリエーションの多さと相まって、設計者を苦しめます。これらの開発者をひどく苦しめる問題に対する根本的な解決法はありませんが、それをある程度和らげる方法はあります。有志があらかじめ製作してくれた、出来合いのUIキットを利用することです。Webアプリケーションの場合、もっとも一般的なのは、Twitter社がオープンソースとして公開しているBootstrapでしょう。

f:id:mochizuki_p:20170127192516p:plain

リスポンシブデザイン

Webアプリケーションの設計で大きな問題となるのは、その利用者が、非常に多種多様なデバイスを利用して、訪れるということです。特に最近ではスマートフォンの普及に伴い、400pxにも満たない小さな画面幅への対応を求められることが多いのですが、しかし、依然としてデスクトップPCのような、1000pxを超えるような大きな画面幅のクライアントにも対応する必要もあります。事態をさらに厄介にするのは、その中間に位置する画面幅をもったタブレットのようなデバイスの存在です。かつては問題は比較的単純でした、大半のアクセスはデスクトップPCからのもので、モバイルからのアクセスは比較的少なく、その画面幅のバリエーションも少なかったので、モバイル専用サイトを別に用意すれば、大抵はことが済んだのです。しかし、今のように画面幅が非常に多様化した世界ではこのアプローチは優れているとは言えません。多種多様な画面幅に柔軟に対応できるようなUI設計が求められているのです。

ここで登場したのが、リスポンシブデザインという概念です。リスポンシブ(responsive)とは、英語で、「すぐに反応する・敏感な」といった意味があります。例を挙げます。このサイトにアクセスして、ブラウザのサイズを変更してみてください。すると、画面幅の変更に対して、画面にぴったりとおさまるようにレイアウトがすぐに対応することがわかります。このようなリスポンシブデザインは、画面幅の変更に柔軟に対応できるという優れた性質を持っています。もちろん、これを一から構築するのは大変で馬鹿げているので、出来合いのものを利用するのがベストでしょう。それがBootstrapです。

Bootstrapの優れた点は、それは単にレイアウトに限定されたものだけではないというところで、ボタンやテーブル、フォームといった一通りのUIがすべてセットになっているというポイントにあります。もちろん、事前にその使い方を把握しておく必要がありますが、その学習コストは比較的低く、一からデザインを実装するのに比べて、はるかに工程を削減できるでしょう。

使い方

Bootstrapの使い方は非常に簡単です。Bootstrap専用のCSSファイルをHTMLファイル上でロードするように設定し、適切な設定を追加すればよいのです。

最初にすべきことは、専用のCSSファイルをロードすることですね。それには主に2つのアプローチがあります。

  • 公式が提供しているCDN、つまり、アプリケーションを利用するユーザーに別サイトからBootstrapを読み込ませる。
  • Webアプリケーションの側でCSSを準備して、ロードさせるようにする。

今回は前者の手法を採用することにします。ここで紹介しているURLを利用しても大丈夫ですが、公式サイトをチェックして最新版を利用するように心がけてください。

f:id:mochizuki_p:20170127192539p:plain

現時点での最新バージョンとして以下のCDNを利用します。

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

グリッドレイアウト

Bootstrapを利用する上で最大の魅力であり、かつ、その威力をてっとり早く体感するにはグリッドレイアウトを試してみるのが一番でしょう。

最初にレスポンシブデザインを利用できない場合の困った現象について例を挙げたいとおもいます。 ここで、あなたはInstagramやピクシブのような画像共有サービスを作りたいとおもっています。事前のマーケティングによって、ユーザーはモバイルからの利用者が多いと想定できたので、モバイルユーザーに最適化したUI設計を行いました。しかし、割合は少ないもののデスクトップユーザーにも対処する必要があります。しかし、デスクトップで表示すると非常にまぬけなUIとなってしまいました。これを見てください。

f:id:mochizuki_p:20170127193050p:plain

画面一面にひどい解像度で拡大された画像が表示されてしまいました。どうしてこのようなことになってしまったのでしょうか? それはこの画像は320x320のサイズであり、それ以上に拡大することが想定されていないからです。もちろん、最近のブラウザでは本来のサイズを超えたとしても、ある程度綺麗に表示されるように なっていますが、それでも限界はあります。この問題を避けるためには、ある程度の大きさ以上のデバイスでは複数の要素を横並びさせる必要がありそうです。 このような場合にBootstrapのグリットレイアウトが役に立ちます。

グリットレイアウトとは?

それは画面のレイアウトを12個のグリッド単位で設計するという思想です。つまり、各横幅は12個のセルで表現され、レイアウトの各要素は、1つまたは複数のグリッドの中に 配置されるように設計するのです。

Bootstrapで想定しているのは以下の4種類のデバイスです。

  • 大きな画面をもったデスクトップPC
  • 比較的大きな画面をもったラップトップPC
  • やや小さめの画面のタブレット端末
  • 小さい画面のモバイル端末

Bootstrapを利用することによって、これら4種類のデバイスに対して、柔軟にレイアウトを変更することが可能になります。具体的なピクセル数を確認してみましょう

以下の表を見れば一目瞭然です。

機種 モバイル タブレット  ラップトップ デスクトップ
画面幅(class=“container"の場合) 768px未満 768px~991px 992px~1199px 1200px以上
コンテナの幅 レスポンシブ 750px 970px 1170px
グリッド数の指定のプレフィックス col-xs-* col-sm-* col-md-* col-lg-*

グリッドクラスは、画面幅がブレークポイント以上のデバイスに適用されます。もし一定以上のサイズでのグリッドを定義していない場合は、一番近いサイズのグリッドに従います。例えば。任意のcol-md-クラスを要素に適用すると、ラップトップPCのスタイルだけでなく、col-lg-クラスが存在しない場合のデスクトップPCのレイアウトにも適用されます。

注意すべき点は、class=“container”を利用する場合、モバイル以外ではコンテナの横幅は固定されている。という点です。そして、各コンテナは基本的に中央寄せになります。もし画面一杯を使うようにしたい場合は、class=“container-fluid"を利用する必要があります。

そして、各横幅12個のセルで表現されるといいました。もし、12以上のアイテムを配置したい場合はどうすれば良いのでしょうか?それはclass=“row"を指定したブロック要素(divかsection)で一番大きな数のcol--で指定した数値の合計が12になるように囲えばよいのです。

Bootstrapはできるだけ多くの要素を同じ行に配置するように自動的に調整します。もし列の合計が12を超える場合は自動的に次のぎょうに 開業して配置されます。もし、12個に満たない場合でも改行を矯正したい場合、次のブロック要素を用意してclass=“row"を指定し、また、新しい要素を続けて配置すればよいのです。

わかりにくいので例をあげましょう。先ほどの画像共有サイトのUIを例にあげます。ここで発生した問題を解決するには、各デバイスの画面幅にあわせて、一列内に配置される画像の数を調整すれば解決しそうです。 たとえば、一番大きな画面幅のデスクトップPCであれば、6個の画像を、ラップトップであれば、3個、タブレットならば2個、モバイルならば1個というふうに、すべて割り切れる数であれば配置が綺麗になるはずです。

いままで説明したルールを元にレイアウトを設定してみましょう。グリットシステムを利用したい箇所全体はclass=“container"で指定すればよいのですね。

<section class="container">
         <div class="col-lg-2 col-md-4 col-sm-6 col-xs-12">
           <img src="FlICmGnj.jpeg"/>
         </div>
         <div class="col-lg-2 col-md-4 col-sm-6 col-xs-12">
           <img src="001.jpg"/>
         </div>
         <div class="col-lg-2 col-md-4 col-sm-6 col-xs-12">
           <img src="linus-eff-you-640x363.png"/>
         </div>
         <div class="col-lg-2 col-md-4 col-sm-6 col-xs-12">
          <img src="Larry_Wall.jpg"/>
         </div>
         <div class="col-lg-2 col-md-4 col-sm-6 col-xs-12">
          <img src="GuidoAvatar_400x400.jpg"/>
         </div>
         <div class="col-lg-2 col-md-4 col-sm-6 col-xs-12">
          <img src="225px-BjarneStroustrup.jpg"/>
         </div>
</section>

画面幅にあわせて自動的にレイアウトが変更される

f:id:mochizuki_p:20170127193334p:plain

f:id:mochizuki_p:20170127193520p:plain

f:id:mochizuki_p:20170127193526p:plain

ネスト

Bootstrapでは割り当てたグリッドの中にも別のグリッドを配置することが可能です。このような設定はどのような場合に役に立つのでしょうか?メインのコンテンツの脇にメニューを配置する場合を考えてみてください。 デスクトップ版では、十分な画面幅があるので、このようなレイアウトは便利ですが、モバイルではメインのコンテンツが見えにくくなり、UXを低下させます。これに対しては、一定以下の画面幅では、メニューをカラム落ちさせて、画面幅いっぱいにメインコンテンツを配置させるようにするといいでしょう。実際に例を見てみます。

<html>
   <head>
      <meta charset="utf-8"/>
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
      <style>
         img{
           width:100%;
           margin:0 auto;
         } 
      </style>
   </head>
   <body>
     <section class="container">
       <div class="row">
         <div class="col-md-9"> 
            <div class="row"> 
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="FlICmGnj.jpeg"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="001.jpg"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="linus-eff-you-640x363.png"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="Larry_Wall.jpg"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="GuidoAvatar_400x400.jpg"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="225px-BjarneStroustrup.jpg"/>
               </div>
            </div>
            <div class="row"> 
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="FlICmGnj.jpeg"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="001.jpg"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="linus-eff-you-640x363.png"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="Larry_Wall.jpg"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="GuidoAvatar_400x400.jpg"/>
               </div>
               <div class="col-lg-2 col-md-3 col-sm-4 col-xs-12">
                  <img src="225px-BjarneStroustrup.jpg"/>
                </div>
              </div>
             </div>
             <div class="col-md-3">
               <div class="list-group">
                 <a href="#" class="list-group-item active">Link</a>
                 <a href="#" class="list-group-item">Link</a>
                 <a href="#" class="list-group-item">Link</a>
                 <a href="#" class="list-group-item">Link</a>
                 <a href="#" class="list-group-item">Link</a>
                 <a href="#" class="list-group-item">Link</a>
                 <a href="#" class="list-group-item">Link</a>
                 <a href="#" class="list-group-item">Link</a>
                 <a href="#" class="list-group-item">Link</a>
                 <a href="#" class="list-group-item">Link</a>
               </div>

            </div>
         </div>
      </section>
   </body>
</html>

f:id:mochizuki_p:20170127193651p:plain

f:id:mochizuki_p:20170127193526p:plain

ヘッダ

Webアプリケーションと言えば、たいていはヘッダがついているものです。それはアプリケーションのホームにジャンプするためであったり、ログイン画面に遷移するためのものであったりします。Bootstrapでは非常に簡単に実装することが可能です。headerタグにclass=“navbar-static-top"を指定して、あとは通常と同じように内部にコンテナを配置していきます。

 <header class="navbar-static-top">
    <div class="container">

...

    </div>
 </header>

サービス名とサービスのホーム画面、ログイン画面へのリンクボタンを設置してみよう。

 <header class="navbar-static-top">
    <div class="container">
      <div class="navbar-header">
        <a href=../ class=navbar-brand>Bootstrap</a>
      </div>
      <nav class="navbar">
         <ul class="nav navbar-nav navbar-right">
              <li><a href="/"><button class="btn btn-default">ホーム</button></a></li>
              <li><a href="/signin"><button class="btn btn-default">ログイン</button></a></li>
         </ul>
      </nav>
    </div>
 </header>


f:id:mochizuki_p:20170127193755p:plain

とても簡単ですね。

ジャンボトロン

たいていWebサービスのフロントページにはキャッチコピーやイメージを表示するための見出し部分があります。

f:id:mochizuki_p:20170128182608p:plain

これはCDNのfastlyのフロントページですが、このような見出し部分をかつてソニーが開発した屋外用巨大モニターにちなんでジャンボトロンと呼ぶそうです。

Bootstrapでこのジャンボトロンを実装するのも非常に簡単です。divやsectionなどのブロック要素に対して、class=“jumbotron”を指定するだけでその箇所がジャンボトロンになります。

<section class="jumbotron">
<h1>Title</h1>
</section>

結果

f:id:mochizuki_p:20170128182626p:plain

フォーム

Webサービスで大事なのは会員登録や投稿画面で使用するフォームのデザインですね。HTMLのデフォルトのデザインはとてもダサいのでBootstrapを使うといいでしょう。

基本的なルール

  • ラベルとフォームをブロック要素(divまたはsection)にclass=“form-group"を指定して囲う
  • すべてのinput,textarea,select要素にclass=“form-control"を指定する

それでは試してみましょう。さきほど設定したジャンボトロンの内部を分割して配置します。

<section class="jumbotron">
<section class="container">
<div class="row">
 <div class="col-md-9 col-xs-12">
<h1>Title</h1>
 </div>
 <div class="col-md-3 col-xs-12">
<form>
  <h2>signin</h2>
  <div class="form-group">
    <label for="email">Email address:</label>
    <input type="email" class="form-control" id="email">
  </div>
  <div class="form-group">
    <label for="pwd">Password:</label>
    <input type="password" class="form-control" id="pwd">
  </div>
  <button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</section>
</section>

結果

f:id:mochizuki_p:20170128182647p:plain

モバイル用メニューの設置

CSSだけでも、リスポンシブなデザインを構築することはできますが、Bootstrap用のJavaScriptファイルを読み込むことでより優れたUIを構築することが可能です。以前に実装したヘッダがありますが、これには1つ残した課題があります。

f:id:mochizuki_p:20170128182657p:plain

モバイルサイズになると、このようにヘッダ内のメニューがカラム落ちしてしまうのです。これはこれで良いという人もいるでしょうが、特にメニューの選択肢が多くなると、メインのコンテンツを完全に覆い隠してしまい。あまり優れたUIとは言えなくなってしまいます。この解決法はBootstrap用のJavaScriptをロードして簡単な設定を行えば、折りたたみ式に変更して、解決することが可能です。実際にJavaScriptを書かなくてもいいのですよ。

BootstrapのJavaScriptライブラリを利用するにはJQueryを事前に読み込んでおくことが必要です。必ず、BootstrapのJavaScriptより前で読み込んでくださいね

jQueryを読み込む

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

Bootstrap用のJavaScriptを読み込む

  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

ボタンを設定

      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
        >
      </button>

モバイルで収納したいメニューの親タグにclass=“navbar-collapse collapse” id=“myNavbar"を設定

      <nav class="navbar-collapse collapse" id="myNavbar">
         <ul class="nav navbar-nav navbar-right">
              <li><a href="/"><button class="btn btn-default">ホーム</button></a></li>
              <li><a href="/signin"><button class="btn btn-default">ログイン</button></a></li>
         </ul>
      </nav>

結果

モバイル版のデフォルトでメニューは収納されています。

f:id:mochizuki_p:20170128182738p:plain

この右上のボタンを押すと

f:id:mochizuki_p:20170128182758p:plain

と展開されて表示されます。