
スクロールに追従するナビゲーションの工夫と実装(2/2)
スクロールに合わせて追従するヘッダをつくる
追従ヘッダは単純なものであれば、CSSだけで実装できてしまう。そこにJavaScriptを使用すると、表示タイミングをコントロールすることができる。まずは、単純にスクロールに追従するだけのヘッダを実装してみよう。また、最後までスクロールするとフッタを表示するようにもしている。

JSで追従・非追従の切り替え
まず、HTMLでヘッダ(ナビやロゴ)とフッタ(SNSボタン)を用意する(01)。
<header class="header js-header"> <!-- 中略 --> </header> <div class="container"> <!-- 中略 --> </div> <footer class="footer js-footer"> <!-- 中略 --> </footer>
CSSだけで実装する場合は、02のように「position: fixed」を利用すれば、画面に固定された状態になり、スクロールしても動かなくなる。ただし、常に表示(追従)した状態となる。
.header{ //中略 position: fixed; top: 0; width: 100%; padding: 10px; box-sizing: border-box; background: #f2f2f2; box-shadow: 0 2px 5px rgba(0, 0, 0, .2); } //中略 .footer{ position: fixed; bottom: 0; width: 100%; transition: all .5s ease; }
次にこの追従ヘッダを、スクロールによって追従・非追従と切り替わるようにしてみよう。先程のCSSを03のように変更する。初期状態として非追従状態と、スクロールした際の追従状態の2パターンを用意する。
.header{ //中略 position: absolute; top: 0; width: 100%; padding: 10px; box-sizing: border-box; transition: all .2s ease; } .header.is-fixed{ position: fixed; background: #f2f2f2; box-shadow: 0 2px 5px rgba(0, 0, 0, .2); }
JavaScript側で行うのはスクロール位置によってclass属性「.is-fixed」の付与・削除を行うだけだ(04)。同じ要領でフッタも実装している。
var $header = $('.js-header'); var HEADER_FIXED_POSITION = 0; //中略 function scrollHandler(){ if($(this).scrollTop() > HEADER_FIXED_POSITION){ $header.addClass('is-fixed'); }else{ $header.removeClass('is-fixed'); } //中略 } $(window).on('scroll', scrollHandler);
なお、CSS側では、追従・非追従が切り替わったときにアニメーションするようにtransitionプロパティを指定している。こうすることで動きやデザインをすべてCSS側で実装することができ、修正にも強くなる。
position:fixed使用時の注意点
position:fixedを使用する際の注意点として、レガシーなスマホ端末でのバグが多く存在することだ。特にAndroid 2系ではviewportに対して、必ず「user-scalable=no」を指定する必要がある。レガシーブラウザへの対応などを考えるときには、fixedを使用すること自体を検討する必要もあるので、注意してほしい。
スクロールの方向に応じて追従ヘッダを表示・非表示する
次に、Case Studyで紹介したハフィントンポストのように、下方向へスクロールしている間は追従ヘッダを非表示にし、上方向へスクロールすると追従ヘッダを表示するようにしてみよう。

JSで表示・非表示の切り替え
この実装には、「通常のヘッダ」「下方向にスクロールしたときのヘッダ」「上方向にスクロールしたときのヘッダ」という3つの段階が必要となる。この3パターンをCSSで作り(05)、JavaScriptでスクロールの位置や方向をもとに切り替えていく(06)。
.header{ //中略 position: absolute; top: 0; width: 100%; padding: 10px; box-sizing: border-box; transition: all .2s ease; } .header.is-fixed{ position: fixed; background: #f2f2f2; box-shadow: 0 2px 5px rgba(0, 0, 0, .2); transform: translateY(-56px); } .header.is-show{ transform: translateY(0px); }
var $header = $('.js-header'); var FIXED_POSITION = 0; var SHOW_POSITION = 60; var beforeScrollTop; function scrollHandler(){ var scrollTop = $(this).scrollTop(); if(scrollTop > FIXED_POSITION){ $header.addClass('is-fixed'); }else{ $header.removeClass('is-fixed'); } if(scrollTop > SHOW_POSITION){ if(scrollTop <= beforeScrollTop){ $header.addClass('is-show'); }else{ $header.removeClass('is-show'); } } beforeScrollTop = scrollTop; } $(window).on('scroll', scrollHandler).trigger('scroll');
スクロールの方向は、イベントが発火したときのスクロールポジションと、その一つ前のスクロールポジションを比較することで判断することができる。現在のスクロールポジションの方が大きければ下方向にスクロール、小さければ上方向にスクロールしていることになる。
スクロールポジションを使った条件を設けてclass属性「.is-fixed」や「.is-show」の付与・削除を行うことで、3パターンを切り替える。
これで下に向かって読んでいる間は、画面を最大限に使用でき、ストレスを減らすことができる。また、上方向にスクロールするときは何か別のアクションを行おうとしていると予想され、そこでメニューを見せてあげることでストレスのない誘導を実現できる。
追従ヘッダを使うときの注意点
追従ヘッダは最近多く取り入れられているUIだ。ロゴを掲載したヘッダは下層からの流入が多いメディアサイトにおいて、トップページへの導線を確保しつつ、名前をはっきりとアピールすることができる。しかし、追従ヘッダは使い方を間違えるとユーザーの視界を必要のない情報で遮り、使い勝手の悪いものになる可能性も含んでいる。使用する際は、その情報を常に見せる必要があるのかしっかりと検討しよう。

- 森田珠奈子
- 独学でHTML・CSSコーディングを学ぶ。大学卒業後、専門学校にてグラフィックデザインを専攻。2012年に(株)LIGに入社。現在はWebデザイナー/イラストレーターとしてデザイン業務に従事している。

- 小見祐介
- カフェでの勤務を経験後、独学でWeb制作を勉強。2013年からWebデザイナーとして働き始める。2015年に(株)LIGに入社。現在はフロントエンドエンジニアとして主にAngularJSを使った案件の開発・運用に従事している。 http://liginc.co.jp/