
カテゴリーが多いスマホサイトで役立つ「スワイプ対応メニュー」(2/2)
[SWIPE TAB 01]タブ部分を配置し横スクロールに対応させる
それでは、スワイプ対応タブメニューをつくってみよう。コンテンツ部分のスワイプ時に連動して、タブメニューをスクロールさせ、常にカレントのタブが表示されるようにする。さらに、タブの切り替時えにアニメーションをつけて、変化をわかりやすくしてみよう。
使用するフレームワークとプラグイン
今回は、jQueryのほかに「Bootstrap※1」というフレームワークと、「Hammer.js※2」というタッチジェスチャーに特化したJavaScriptライブラリを使用する。この二つを組み合わせることによって、上記で述べたような操作に対応したタブメニューを実装できる。
タブ部分の配置と横スクロール対応
まず、Bootstrapを使い、ベースとなるタブメニューを実装する(01)。
<div class="nav-tabs-outer"> <ul class="nav nav-tabs js-tabs"> <li class="active text-center"><a href="#tab1" data-toggle="tab">TAB1</a></li> 省略 <li class="text-center"><a href="#tab10" data-toggle="tab">TAB10</a></li> </ul> </div>
そのままでは、タブの数が多くなると画面内に回りこんでしまうので(02)、CSSとJavaScriptで常に横一列になるようにし、横スクロールに対応させる。

Bootstrapのコンポーネントのままだと、タブ数が多くなると、回りこんでしまう
JavaScriptでタブを囲っている要素に対して横幅を指定する(A)。このとき、タブの全体数を取得し、その分の横幅を指定しよう。タブの全体数は実装後に変動することがあるので、固定値にしないほうが汎用性があってよい。
$(function(){ var $jsTabs = $('.js-tabs'); var $jsTabsLi = $('.js-tabs li'); var tabsLiLen = $jsTabsLi.length; var tabsLiWid = $jsTabsLi.eq(0).width(); //タブエリアの横幅指定 $jsTabs.css('width',tabsLiWid * tabsLiLen); //--------A });
さらに、それを囲うdiv要素にCSSで「overflow-x:scroll;」を適用し(B)、そのdiv要素からはみ出た部分を横スクロールで表示できるようにする。
.nav-tabs-outer{ overflow-x:scroll; //--------B } .nav-tabs-outer .nav-tabs li{ display: block; width: 100px; }
これらの処理により、画面上に表示されるタブメニューの範囲が制限され、ユーザーの操作性を考慮したサイズ・配置を実装することができる。

CSSとJavaScriptで横スクロール対応のタブにしたところ
[SWIPE TAB 02]スワイプでタブが切り替わるようにする
タブメニューを配置して横スクロールに対応させたところで、次はタブによって切り替わるコンテンツ部分の挙動を実装していこう。コンテンツ部分に対し、スワイプ操作によってタブ切り替えができるようにし、使い勝手をよくする。
コンテンツ部分のスワイプの実装
スワイプ操作が有効なコンテンツ部分(ここではclass属性「.js-swipe」のdiv要素)に対して、jQueryでswipeleftイベントと、swiperightイベントを登録する。これらはjQueryには用意されていないイベントだが、Hammer.jsを導入することによって使用可能になる。
$(function(){ var ACTIVE_SELECTOR = '.nav-tabs > .active'; var $jsTabs = $('.js-tabs'); var $jsTabsLi = $('.js-tabs li'); var $jsSwipe = $('.js-swipe'); var $scrollContainer = $('.nav-tabs-outer'); var tabsLiLen = $jsTabsLi.length; var tabsLiWid = $jsTabsLi.eq(0).width(); //タブエリアの横幅指定 $jsTabs.css('width',tabsLiWid * tabsLiLen); //スワイプイベント登録 $jsSwipe.hammer().on('swipeleft',next); //--------C $jsSwipe.hammer().on('swiperight',prev); function next() { tabManager($(ACTIVE_SELECTOR).next('li')); } function prev() { tabManager($(ACTIVE_SELECTOR).prev('li')); } //--------C // 指定されたタブをカレントし要素にスクロールする function tabManager($nextTarget){ $nextTarget.find('a').trigger('click'); //--------D if($nextTarget.index() != -1){ $scrollContainer.scrollLeft($nextTarget.index() * tabsLiWid); //--------E } } });
スワイプした方向によってタブが前後に移動するので、カレント処理をしている関数に対して、引数で次にカレントにする要素を渡して実行する(C)。
そして、関数側で受け取った要素に対してclickイベントを実行し、カレント位置を移動させる(D)。
カレント処理について
タブメニューを横スクロールすると、カレントのタブが画面外に隠れてしまうことがある。ユーザーが現在位置を見失うので、どのタブがカレントなのかわかりやすいように、タブ切り替えが行われた際、画面上にカレントのタブが移動してくるようにする(E)。こうすれば、ストレスなく情報が入ってくる。

タブメニュー部分だけでなく、コンテンツ部分でもスワイプでタブ切り替えができるようになった(sample02)
スワイプ実装の注意点
スワイプを実装する際には、通常のページスクロール操作に反応しないように制御が必要だ。この制御を省いてしまうと、ユーザーの予期せぬタイミングでタブが切り替わったり、ページスクロール中にスワイプが反応してしまったりして、逆に使いづらいUIになってしまう。Hammer.jsはその辺りも対応しているが、一から自作で実装するときは注意しよう。

応用編として、タブが切り替ったことがよりわかりやすくしたサンプルを用意した(sample03)。カレントのタブの背景に色を付け、さらにアニメーションを追加して「タブが切り替わった」ことが視覚的に伝わるようにしている。実際に操作してみるとsample02との違いが体感できるので、ぜひダウンロードして試していただきたい
※1 HTML、CSS、JavaScriptのフレームワークの中でメジャーなものの一つ。サンプルでは、全体のstyleとベースとなるタブ切り替えで使用している。http://getbootstrap.com/
※2 今回はスワイプのイベント登録に使用しているが、他にもさまざまなジェスチャーが用意されている。また、サンプルのようにjQueryプラグインとして使用することも可能だ。http://hammerjs.github.io/

- 町田なつみ
- デジタルハリウッドにて、グラフィックデザインを専攻。卒業後は制作会社にてWebデザイナー/ディレクターを経験し、2014年より(株)LIGに参画、Webデザイナーとして業務に従事している。

- 古川佑太朗
- 2011年、東京デザイナー学院を卒業。同年、Web制作会社で働きはじめ、代理店経由の案件を数多く経験する。その後、2015年より(株)LIGにフロントエンドエンジニアとして入社。現在は、新規案件の開発業務を中心に従事している。