久々にUI実装系の記事を書きます。Google Analyticsで当ブログのオーガニック検索キーワードを見ていると、「スクロール」、「ヘッダーバー」を使った複合検索でのアクセスが目立っていたりします。確かに最近はスクロールを合わせてヘッダーバーを表示させたり、非表示にさせたりするUIが至るところで見受けられるようになっています。自分もそれほど気にはしていませんでしたが、今回どんな方法で実装できるか試してみることにしました。いくつか紹介していきます。

目次
はじめに – ヘッダーバーの準備
早速、スクロールするとスライドして現れる「ヘッダバー」の実装方法について説明していきます。「ヘッダーバーはページの読み込み時は非表示となっており、ページを下にスクロールすると表示される」という機能を実装していきます。
ベースとなるヘッダーバー HTML / CSS
まず今回の実装のベースとなるヘッダーバーを以下のように設定しました。こちらのヘッダバーを使って機能を実装していくことにします。
<header class="cb-header">header</header>
header {
background-color: #000;
line-height: 56px;
text-align: center;
width: 100%;
color: #fff;
}
jQueryを読み込む
それからjQueryを使いますので、予めページに読み込んでおく必要がありますので、忘れないようにしてください。
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
jQueryのslideDown()、slideUp()を使った実装方法
まず自分が最初に思いついたやり方です。jQueryのslideDown()メソッド、slideUp()メソッドを使った実装します。これが一番簡単な方法ですかね。メソッドの詳細は以下を参照してください。
jQueryのslideDown()、slideUp()を使った実装デモ
まずは以下のデモをご確認ください。
CSSの設定
まず、ヘッダーバーに対してCSSを設定していきます。ポイントは「position: fixed;」でページ上部に固定させた状態で、「display: none;」で非表示とさせておきます。
.cb-header {
position: fixed; /* ヘッダーバーを固定 */
top: 0; /* 上から0の位置に固定 */
left: 0; /* 左から0の位置に固定 */
display: none; /* ヘッダーバーを非表示 */
}
JavaScript(jQuery)の設定
JavaScriptの実装は以下のように数行ですみます。処理としては、「scroll」のイベントを取得した際に、スクロールの位置(scrollTop()の位置)が「0」より大きければ、ヘッダーバーに対してsideDwon()メソッドを実行して表示させ、「0」であれば、ヘッダーバーに対してslideUp()メソッドを実行して非表示にしています。
$(function () {
// scrollイベントを取得した際の処理を定義
$(window).on("scroll", function () {
// scrollTop()が0より大きい場合
if ($(this).scrollTop() > 0) {
// ヘッダーバーをslideDownして表示
$(".cb-header").slideDown();
// scrollTop()が0の場合
} else {
// ヘッダーバーをslideUpして非表示
$(".cb-header").slideUp();
}
});
});
slideDown()、slideUp()を使う実装の利点は、slideDown()であれば閉じた状態、slideUp()であれば開いた状態にしか有効とならない点だと思っています。ページをスクロールしていれば、たえずscrollイベントが発生した状態となっており、同じ処理が何回も実行されてしまうので、通常であれば何回も実行されないような処理を書く必要があります。slideDown()、slideUp()は、すでにそういった処理が実装されているので、上記のようにシンプルに実装することができます。
ただ、実際に実装したものを見て思ったのは、ヘッダーバー自体が動いているのではなく、単にヘッダバーが閉じたり、開いたりしているのに過ぎないということです。「ヘッダーバーの中のテキストが動いていない」という所にどうしても納得がいかなく、他の方法を模索することにしました。
CSSアニメーションを使った実装方法
次に試してみたのがCSSアニメーションを使った実装です。これはプロトタイピングツールでお馴染みのprottのサイトを参考にさせていただきました。prottのサイトはまさに今風のUIデザインがふんだんに取り入れられていて、ヘッダバーの表示/非表示機能も当たり前ですがかなりイケてる感じで実装されているサイトとなっています。ヘッダバーもそれ自身がちゃんと動くように実装されています。
そんなprottのサイトを調べてみると、ヘッダーバーの表示/非表示機能はCSSアニメーションを使って実装されていました。CSSアニメーションは、animationプロパティとそのサブプロパティ、@keyframesを使ってアニメーションを実現させます。詳細は以下を参照してください。
CSSアニメーションでの実装デモ
まずは以下のデモをご確認ください。
CSSの設定
CSSアニメーションと言うだけあり、CSSの実装がなかなかヘビーです。分解して説明していきます。(ベンダープレフィックスは省略しています。必要に応じてつけてください。)
まずはヘッダーバーのスタイルの設定です。「position: fixed;」で固定し、さらに「top: -56px」でヘッダバーの高さ分だけ画面の上に隠すようにして非表示にさせています。
.cb-header {
position: fixed;
top: -56px;
left: 0;
}
隠しておいたヘッダバーを表示させるためのスタイルの設定です。アニメーション名を「slideDown」として、アニメーションのスタート地点である「0%」の「top: -56px;」からゴール地点の「100%」の「top: 0;」にかけてのアニメーションに関する設定をしています。
.slide-down {
animation-name: slideDown;
animation-timing-function: ease-in;
animation-iteration-count: 1;
animation-delay: 0s;
transform-origin: 50% 50% 0;
animation-duration: .5s;
top: 0;
}
@keyframes slideDown {
0% {
top: -56px;
}
100% {
top: 0;
}
}
こちらは表示されているヘッダーバーを再度隠すためのスタイルの設定です。アニメーション名を「slideUp」として、アニメーションのスタート地点である「0%」の「top: 0;」からゴール地点の「100%」の「top: -56px」にかけてのアニメーションに関する設定をしています。
.slide-up {
animation-name: slideUp;
animation-timing-function: ease-in;
animation-iteration-count: 1;
animation-delay: 0s;
transform-origin: 50% 50% 0;
animation-duration: .5s;
top: -56px;
}
@keyframes slideUp {
0% {
top: 0;
}
100% {
top: -56px;
}
}
JavaScript(jQuery)の設定
CSSアニメーションで実装する場合も、JavaScriptの設定が必要です。基本は先に紹介したjQueryのslideDown()、slideUp()を使った実装と同じです。
scrollTopの位置によって、上記で設定したcssのclass属性を適用させたり、取り外したりする処理を実行させるようにするだけです。
それから、今回の実装においては、flagを使うようにしています。上記でも触れたように、ページをスクロールしていれば、たえずscrollイベントが発生した状態となっており、同じ処理が何回も実行されてしまいます。それを避けるために、upとdownを指定するflag変数を用いて制御することにしています。
実際のコードは以下のようになります。
$(function () {
// falg変数のデフォルト値として「up」を指定
var flag = "up";
// scrollイベントを取得した際の処理を定義
$(window).on("scroll", function () {
// scrollTop()が「0」より大きい場合
if ($(this).scrollTop() > 0) {
// flag変数が「up」だった場合の処理
if (flag === "up") {
// ヘッダーバーにslide-upクラス属性を付与(表示)
$(".cb-header").removeClass("slide-up");
// ヘッダーバーからslide-downクラス属性を取り外す
$(".cb-header").addClass("slide-down");
// flag変数の値を「down」に変更
flag = "down";
}
// scrollTop()が「0」の場合
} else {
// flag変数が「down」だった場合の処理
if (flag === "down") {
// ヘッダーバーにslide-downクラス属性を付与(非表示)
$(".cb-header").removeClass("slide-down");
// ヘッダーバーからslide-upクラス属性を取り外す
$(".cb-header").addClass("slide-up");
// flag変数の値を「up」に変更
flag = "up";
}
}
});
});
jQueryのslideDown()、slideUp()を使った実装と違って、ヘッダーバー自体が動くようになっており、かなりいい感じの実装となります。ただ@keyframesをはJavaScriptやjQueryで扱いにくく(CSSStyleSheet.insertRuleを使えば扱えないこともないですが)、汎用的に使うのがやや困難となります。
jQueryのanimate()メソッドを使った実装方法
そこで最後に行き着いたのが、jQueryのanimate()メソッドを使った実装です。CSSアニメーションを使った実装と同じような動きを実現し、しかもシンプルにかけるので、コード量はだいぶ抑えられます。animate()メソッドについては、詳細は以下を参照してください。
jQueryのanimate()での実装デモ
まずは以下のデモをご確認ください。
CSSの設定
CSSの設定はこれだけです。「position: fixed;」で固定し、さらに「top: -56px」でヘッダバーの高さ分だけ画面の上に隠すようにして非表示にさせています。
.cb-header {
position: fixed;
top: -56px;
left: 0;
}
JavaScript(jQuery)の設定
JavaScriptもかなりシンプルです。基本は先に紹介したCSSアニメーションを使った実装と同じです。こちらの実装においても、scrollイベントの発生中に同じ処理が何回も実行されるのを避けるために、upとdownを指定するflag変数を用いることにします。
それから、animate()メソッドを使用する際の注意点として、animate()メソッドはイベントが発生した数だけ実行されるようになっています。そこでanimate()メソッドを実行する際は、stop()メソッドを使って、実行中のアニメーションを中止させてから実行するようにします。
実際のコードは以下のようになります。animate()メソッドを使って、topの位置をアニメーションをかけながら変更するような処理となります。
$(function () {
// falg変数のデフォルト値として「up」を指定
var flag = "up";
// scrollイベントを取得した際の処理を定義
$(window).on("scroll", function () {
// scrollTop()が「0」より大きい場合
if ($(this).scrollTop() > 0) {
// flag変数が「up」だった場合の処理
if (flag === "up") {
// ヘッダーバーに対して、stop()メソッドを実行してから、
// animate()メソッドを実行
$(".cb-header").stop().animate({
// topの位置を「-56px」から「0」になるまでアニメーション
top: 0
// アニメーション時間を「500ms」に設定
}, 500)
// flag変数の値を「down」に変更
flag = "down";
}
// scrollTop()が「0」の場合
} else {
// flag変数が「down」だった場合の処理
if (flag === "down") {
// ヘッダーバーに対して、stop()メソッドを実行してから、
// animate()メソッドを実行
$(".cb-header").stop().animate({
// topの位置を「0」から「-56px」になるまでアニメーション
top: "-56px"
// アニメーション時間を「500ms」に設定
}, 500);
// flag変数の値を「up」に変更
flag = "up";
}
}
});
});
自分としては、最もこの実装方法がシンプルで気に入っています。アニメーションの動きもしっかりしています。しっかり検証していませんが、今の所は申し分ない実装方法かなと思っています。
表示/非表示のブレイクポイントを変更する
上記で紹介したものはすべてスクロールした瞬間にヘッダバーが表示されるようになっています。というのもスクロールのブレークポイントを「0」に設定しているからです。これをある程度スクロールしてからヘッダーバーを表示させるようにすることも可能です。
例えば、ページ上部から300pxスクロールしたところで、ヘッダバーを表示させる場合は、以下のマーカーの部分に「300」と指定するだけでOKです。
$(function () {
$(window).on("scroll", function () {
if ($(this).scrollTop() > 300) {
} else {
}
});
});
こうすることで、好きな位置でヘッダバーの表示/非表示の制御ができるようになります。上記で紹介したflag変数を使った処理の制御もこのようにブレイクポイントを0以上に設定した時にますます生きてくるようになります。
反対の実装をする – スクロールしたらヘッダーバーを隠す
これまで紹介してきたのは、ページをスクロールした時に非表示になっていたヘッダーバーを表示させる方法でした。その反対で、ページをスクロールしたら、表示させていたヘッダバーを非表示にするという実装方法も紹介しておきます。このように実装しているページもよく見かけます。
実装方法は、上記で紹介したコードを用いれば簡単です。表示と非表示の処理を入れ替えるだけです。jQueryのanimate()メソッドを使った実装方法を例として入れ替え方を以下に説明していきます。
ページをスクロールしたら隠れるヘッダーバーの実装デモ

まずは以下のデモをご確認ください。
CSSの設定
topの値として「-56px」を指定していた所を「0」にします。つまりページ読み込み時は、ヘッダーバーは表示された状態となります。
.cb-header {
position: fixed;
top: 0;
left: 0;
}
JavaScript(jQuery)の設定
変更箇所はマーカーの部分となります。なんと「0」と「-56px」を入れ替えるだけでOKです。
$(function () {
var flag = "up";
$(window).on("scroll", function () {
if ($(this).scrollTop() > 0) {
if (flag === "up") {
$(".cb-header").stop().animate({
top: "-56px"
}, 500);
flag = "down";
}
} else {
if (flag === "down") {
$(".cb-header").stop().animate({
top: 0
}, 500)
flag = "up";
}
}
});
});
まとめ
今風のサイトを作るなら、ヘッダーバーの表示/非表示の制御は必須となってくるでしょう。今回はスクロールするとヘッダーが表示させる方法と、ヘッダーバーが非表示となる方法を紹介しました。この2つをうまく組み合わせて、ブレイクポイントを調整しながら、複数のヘッダバーを実装すると、面白いUIを持った使い勝手の良いサイトを作ることができるようになるのではないでしょうか。
今回はアニメーションを実装するのに、jQueryとCSSを使いましたが、Web Animations APIのブラウザの実装が進めば、JavaScriptオンリーでアニメーションも簡単に書けるようになりますね。
それから今回この記事を書きながら、汎用的に使えるようにjQueryのプラグインも同時に作っていました。本当はこの記事内で紹介しようと思ったのですが、長くなりすぎたので、jQueryプラグインの紹介は次回以降にします。
追記(2015-7-25): jQueryプラグインに関する記事を書いたので紹介します。併せてご確認ください。
コメント