rcmdnk's blog

20141202_mobile_200_200

Bootstrap 3でモニタ用的なテンプレートを作ってみた に引き続き、今度は実際に作ってみたものの紹介。

実際に作ってみた物

Bootstrap Test

このページになります。

上に固定のナビゲーションヘッダーがあって、そこに2つのドロップダウンボタン が設置してあります。

ここっではSabi組とSango組に分けています 1。

下側は2つの画面に分かれていて、左側がサイドバー的な存在。 右側がメインコンテンツ、的な役割です。

full

これは画面が十分大きな場合。

Sabi組、Sango組それぞれにいくつかのコンテンツがあって、 上のドロップダウンボタンからどちらかの1つを選んだ時、 全体もその選んだ方の組に移ります。

サイドバーには組内の全てのコンテンツ、メインの右側には現在選択中のコンテンツが載ります。

さらに、サイドバーの各領域をクリックした時にもメインの画面が変わるようになっています。

また、サイドバー、メインコンテンツはそれぞれ別々のスクロール領域を持っていて、 縦にはみ出る様な場合には、それぞれ別個にスクロール出来るようになっています。

また、幅が狭くなってくると、途中でサイドバーは消える様になっています。

さらに幅を狭めていくと、携帯用に、上のナビゲーションバーもcollapseさせて 全体で1つのドロップダウンボタンみたいになります。

mobile

パソコンサイズだと結構しょぼいですが、携帯サイズのドロップダウンの感じは 簡単に作れる割には割りとしっかりしてる感。

取り敢えずこんな感じです。

以下、適当に補足。 各コンテンツの使い方とかは本家 2 に例が沢山載ってて分かりやすいので それ以外で色々やったこととか。

collapseするタイミングを変更する

これは公式にも大きく書いてありますが、 ナビゲーションバーをcollapseするようにしている場合、 デフォルトでは768px(タブレットサイズ)より小さくなった場合に collapseしてボタン化する様になっています。

今回はドロップダウンメニュー2つだけでそれだとちょっと早いので、 550px程度まではボタンを全て見せたままにしたいと思いました。

この様に、Bootstrapの中のデフォルト値を弄りたい場合は、 bootstrapより先に読み込んでる _bootstrap-variables.scssの中で値を変更します。 このファイルは最初全てコメントアウトしてありますが、 それぞれデフォルト値が書いてあるので、それを参考にしながら変更することが出来ます。

今回やったのは

$grid-float-breakpoint:     550px;

です。これで550pxを境にナビゲーションバーがcollapseします。

ただ、名前を見て分かる通り、これは他のところにも影響するので注意。 他にもこの値を使う所があってそこはそのままにしたい場合には、 collapseを遅らせたい要素にクラスを与えてごにょごにょしていく必要があります。

favicon

特にBootstrapというわけではないですが images/favicon.pngとか置いておいて、 index.htmlのhead内で

<link href="images/favicon.png" rel="icon">

と書いておけばfaviconの設定が出来ます。

タブ同士をJavaScriptで結びつける

今回はタブを沢山使ってます。

role="tablist"を持った親要素で囲って、 その中にrole=presentationを持った子要素を配置していきます。

この子要素の中にa要素を含ませ、それがタブになります。 この子要素がactive担った時、a要素で指定されたidの要素が 表示される様になります。

今回の例では、まず、2つのDropdownメニューの中のリストがそれぞれ タブ群になっていて、それらのタブは右下のメインのコンテンツに結びついています。

さらに

1
2
3
4
<ul class="nav navbar-nav main-tab noshow" role="tablist">
  <li role="presentation" class="active"><a href="#sabi-tab" aria-controls="sabi-tab" data-toggle="tab"></a></li>
  <li role="presentation" class=""><a href="#sango-tab" aria-controls="sango-tab" data-toggle="tab"></a></li>
</ul>

というタブも作っています。この中にあるnoshowクラスは

1
2
3
.navbar-collapse.collapse .noshow {
  display: none;
}

こんな感じでまさにただ消しているだけです。

このタブはSabi組/Sango組の選択をするものですが、 実際にはこれらの組の選択は、各コンテンツを選んだ時に 選ばれたコンテンツの入ってる方を表示する、と言う事をするので、 擬似的にタブ化するために見えないタブを作っています。

これで、実際にドロップダウンからコンテンツが選択された時には、 そのidをcとして

$(c).on('show.bs.tab', function...

と動作を与えることが出来るので、ここで組のタブを切り替える様な関数を呼びます。

1
2
3
4
5
6
7
8
9
10
11
12
13
$(function() {
  function switchTab(c){
    if(c.indexOf('sabi') == 0){
      $('body').removeClass('sango');
      $('body').addClass('sabi');
      $('.main-tab a[href="#sabi-tab"]').tab('show');
    }else{
      $('body').removeClass('sabi');
      $('body').addClass('sango');
      $('.main-tab a[href="#sango-tab"]').tab('show');
    }
  }
});

こんな感じで、要素がsabiなのかsangoなのかみて、 tab('show')関数でmain-tabの切替を行っています。

メインのコンテンツはsabi-firstやsango-secondと言った名前になってるので、 その先頭をみて判断する形。

また、ここでbodyにもクラス名を与えたりしてますが、 これによって全体の背景色を変更しています。

on('show.bs.tab')とtab('show')の基本的な組み合わせだけで 色々とタブ同士をつなぎ合わせることが出来ます。

JavaScript · Bootstrap

サイドバーにも結びつける

サイドバーもsabi-first-sidebarみたいなidを持っていて、 これがクリックされた際にはsabi-firstをtab('show')して、みたいなことを行います。

逆に、メインコンテンツのsabi-firstがドロップダウンから選択された場合には sabi-first-sidebarもactiveにして、 サイドバーの場合にはタブでは無いですがactiveが付いてる場合は 背景を少し暗くする、的なことをCSSでしています。

ホントはサイドバーとメインコンテンツが同じ要素として扱えれば良いんですが、 その辺の良いやり方が思いつかなかったので別の要素として作っておいて JavaScriptでむりくり繋げる形にしました。

ナビゲーションバーのcollapseされたボタンから表示後、クリックで戻す

collapseされた後のナビゲーションバーのボタンは、 一度押すとボタンを縦に表示してくれますが、 これがその中のボタンを押してもただのタブの切替とかだと ナビゲーションバーのボタンがそのまま表示され続けます。

これを避けるために、myscript.jsに

1
2
3
4
5
$(function() {
  $('.navbar-collapse .dropdown li a').click(function() {
    $('.navbar-collapse').collapse('hide');
  });
});

という関数を定義して、collapseした後に出来るナビゲーションバーの ドロップダウンボタンは中身がクリックされたらすぐに元に戻る様にしています。

クッキーを使ってタブを記録

通常、先のページをリロードすると、HTMLのソースでactiveのクラスを 指定してあるものが選択された状態に戻ってしまいます。

これを、最後に選択したものから再び始められるよう、 Cookieを用いて元の状態に戻してあげます。

こちらのGitHubに公開されているjquery-cookieというjQueryのプラグインを使います。

まず、このレポジトリからjquery.cookie.jsを取ってきて javascriptsへ追加。

index.htmlのmyscript.jsの前ににこれを追加。

<script src="javascripts/jquery.cookie.js"></script>
<script src="javascripts/myscript.js"></script>

これで$.cookie()という関数が使える様になります。

Cookieに保存したいときは

$.cookie('active-c', 'content-name', {expires: 600});

とすると、active-cというCookieの値にcontent-nameという文字列を記憶します。 expiresでこれを破棄するまでの時間指定です。(600秒で10分。)

タブを切り替えた時をタブコンテンツのshow.bs.tabで捉えて、 その時にCookieを保存してあげます。

myscript.js
1
2
3
4
5
6
7
8
9
$(function() {
  $('.c-menu a[data-toggle="tab"]').on('show.bs.tab', function (e) {
    var c = e.target.href.split("#")[1];
    $('.c-menu a[data-toggle="tab"]').not('a[href=#'+c+']').parent().removeClass('active');
    switchTab(c);
    switchContent(c);
    $.cookie('active-c', c, { expires: 600 });
  });
});

$.cookie('active-c')みたいにキーワードだけ入れるとそれに対応する Cookieに保存された値が帰ってくるので

myscript.js
1
2
3
4
5
6
$(function() {
  if($.cookie('active-c')){
    var c = $.cookie('active-c');
    $('.c-menu a[data-toggle="tab"]').parent().removeClass('active');
  }
});

みたいな事をすればページをロード時に必要なタブを選択することが出来ます。

myscript.js

font-awesomeなボタン

組のドロップダウンメニュー内は <i class="fa fa-area-chart"> ()を付けて居ます。

また、Dropdownメニューの表示自体も、通常 <span class="caret"></span> を使ってキャレットを表示させますが、上では <i class="fa fa-area-chart">} () を使っています。

Bootstrapと非常に相性が良いアイコンたちです。

Icons Font Awesome

各要素ごとでスクロールさせる

上のページの下の2つの要素は別々にスクロールされます。 また、ページ全体としてはFixしてスクロールしないようになって、 常に周りが組の色で囲まれてるようにしています。

やってることはこんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
<body class="sabi">
  <div class="tab-pane active" id="sabi-tab">
    <div class="row-fluid scroll-row">
      <div class="col-sm-3 hidden-xs sidebar">
      ...
      </div>
      <div class="col-sm-9 col-xs-12 main">
      ...
      </div>
    </div>
    </div>
</body>

こんな感じのHTMLに対して、

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
.sabi {
  background-color: $sabi-color;
}
.sango {
  background-color: $sango-color;
}
#sabi-tab, #sango-tab{
  top:0;
  left: 0;
  right: 0;
  bottom: 0;
  position: absolute;
}
.scroll-row {
  margin: 6.5rem 1rem 1rem 1rem;
  height: calc(100% - 8rem);
  background: white;
}
.main, .sidebar{
  height: 100%;
  overflow-y: scroll;
a .sidebar-panel {
    height: 30rem;
    border-width: 0 0 1rem;
    border-style: solid;
    &.active {
      background: darken($background, 10%);
    }
  }
}

この様なスタイルを当てます。

まず、bodyにはJavaScriptでsabiかsangoのクラスが付けられるので、 それで全体の背景色がsabi色かsango色になります。

その次に、一度positon:absolute;の要素(#sabi-tab)で全体を囲って、 その中に上にmarginを多めに取った要素(.scroll-row)を作ります。

これは、ナビゲーションバーをnavbar-fixed-topで作っていて、 上に固定になっているためです。 固定化する、ということは、実際には下の要素の上に被って上側に張り付いてるだけなので、 普通に全体を使ってしまうと上の方でコンテンツが ナビゲーションバーの下に隠れてしまいます。 ので、その分、6.5remと多めのマージンを取って、 ナビゲーションバーから見える部分が丁度他と同じ位になるようにしています。

また、その分上の部分を下げるので、全体として、100%より小さくしないと この要素の大きさのせいで下にはみ出てしまって全体がスクロールされてしまうので、 それを避けるために100%から少し小さい大きさにしています。

そして、この要素の背景を白に戻して、結果的に、 マージン分含め外側が枠線になるような感じ出来ます。

次に、この.scroll-rowの中に、100%の高さを持ったmainとsidebarを作ります。 それぞれ高さを100%にしながらoverflow-y: scrollをすることで、 はみ出た分はそれぞれで勝手にスクロールする様にすることが出来ます。

取り敢えずそんな感じです。

Sponsored Links
  1. 人気色ランキング - Popular Colorsで 人気のあるものから適当にピックアップして、それぞれ色の名前です。 ↩

  2. Components · Bootstrap ↩

Sponsored Links

« Bootstrap 3でモニタ用的なテンプレートを作ってみた socatを使ってソケットテストする »

}