スクロールをセクションごとに制御してくれるプラグイン「jQuery Scrollify」。主に縦に長いLPなどでよく使用されているので、ちょこっとスクロールしただけで、次のセクションまでスルスルとスクロールしていくサイトに出会ったことがある方もいるはず。
ユーザーに面白いUX(ユーザーエクスペリエンス)を与えることができるプラグインですので、使い方を詳しく解説していきます。
Contents
メリット
以前「waypoint.jsとCSSでスクロールして画面指定位置で要素をアニメーションさせる」というのをアップしました。
このようなアニメーションと非常に相性がいいです。
スクロール位置を発火点にアニメーションしている場合、スクロール位置を完全に制御できるので、ユーザーが中途半端なところでスクロールをやめてしまったり、戻ったり、といった残念なことになりません。プレゼンテーションのスライドを1枚ずつ見せるようなイメージにできます。
デメリット
デメリットとしては、スクロール制御がうまくいかないと最悪です。1つ下のセクションにスクロールしたかったのに2つ先まで一気に行っちゃったり。。。上に戻ろうとしたら戻れなくなっちゃったり。。。
何度もそんな目に遭遇しました。そうなるともう「ブラウザバック」で「サヨウナラ」です。
プラグインによっては特定のブラウザとの相性が悪い場合もありますので、採用する際は主要なブラウザで入念にチェックをしましょう。
設置方法
「jQuery Scrollify」サイトからソースコード一式をダウンロードするか、CDNで設置します。
github
https://github.com/lukehaas/Scrollify
デモサイト
https://projects.lukehaas.me/scrollify/
CDNで設置
以前に「CDNならこのサイトが超便利!jsDelivrの使い方」という記事で書いたjsDelivrにもCDNのリンクがあります。
今回はこちらのCDNで実装します。
基本的な使い方
jQuery本体と「jQuery Scrollify」をhead内に設置します。
(ダウンローして設置する方はパスを変更してください。)
JS
<script src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-scrollify@1/jquery.scrollify.min.js"></script>
次にベースのHTMLです。
HTML
<div class="box box1">
<h2>box1</h2>
</div><!--box-->
<div class="box box2">
<h2>box2</h2>
</div><!--box-->
<div class="box box3">
<h2>box3</h2>
</div><!--box-->
<div class="box box4">
<h2>box4</h2>
</div><!--box-->
「.box」がスクロールさせる各セクションになります。
CSS
*{
box-sizing: border-box;
margin: 0;
padding: 0;
}
.box{
color: #fff;
padding: 40px;
}
.box1{
background: #F43959;
}
.box2{
background: #4CA4CF;
}
.box3{
background: #e5cf54;
}
.box4{
background: #45CB99;
}
CSSは「.box」のスタイリングしているだけなので適宜お好みで。
では、いよいよスクロールさせるためのコードを記述します。
JQuery
$.scrollify({section:".box"});
たった1行です。基本的な動きだけならこれだけです。オプション値の「section」にスクロールさせたい要素を設定します。今回は「.box」です。
以前、「ボックスの高さをブラウザの高さに合わせるテク3つ!」という記事を書きました。
この後のオプション値で触れますが、「setHeights」のオプションを特に設定しなければ、セクションの高さがブラウザの高さより低い場合はブラウザの高さに自動で合わせてくれます。
ブラウザの高さより高い場合はそのままの高さになります。
ブラウザの高さを変えるとずれる
しかし残念なことに、ブラウザの高さを変えるとスクロール位置がすれてしまいます。先ほどのサンプルでスクロール途中でブラウザの高さを変えてみてください。
オプション値の「setHeights」はブラウザリサイズ時に常にセクションの高さをブラウザの高さに合わせてくれるのですが、スクロール位置までは変えてくれないので、途中までスクロールしている際はずれます。下に行けば行くほどズレは顕著になります。
せっかく高さを合わせてくれる「setHeights」ですが、思うようにいかない動きをするので「false」にしてしまい、CSSでセクションの高さを設定するようにします。では、修正していきましょう。
HTMLは変更なしです。
CSS
.box{
color: #fff;
height: 100vh;
padding: 40px;
}
3行目
「setHeights:false」にするのでセクションの高さをCSSで設定しています。
Jquery
var current;
$.scrollify({
section:".box",
setHeights:false,
before:function(i,box){
current = i;
},
});
$(window).on('resize',function(){
if(current){
var currentScrl = $('.box').eq(current).offset().top;
$(window).scrollTop(currentScrl);
}
});
1行目
現在表示中のセクション番号を格納する変数「current」を定義。
4行目
前述の通り「setHeights」を「false」にします。
5,6行目
「before」はスクロール前に発生します。引数で表示するセクションの番号と、スクロール制御を設定したセクション要素が取得できます。
ですので「current = i;」とすることで、スクロールするたびに現在表示中のセクションの番号を取得しています。
11,12行目
ブラウザがリサイズされたら、現在表示しているセクションの位置へスクロールしています。
サンプルで確認してみてください。ブラウザの高さを変えてもずれなくなっています。
オプション値
基本ができましたのでオプションの値を見ていきましょう。
(私の英語力が残念なのでGoogle先生の直訳です。)
section | ページのセクションのCSSセレクター。 |
---|---|
sectionName | Scrollifyでは、各セクションのハッシュ値を定義できます。 これにより、特定のセクションにパーマリンクすることが可能になります。 これはセクションのデータ属性として設定されます。 データ属性の名前は ‘sectionName’によって定義されます。 |
interstitialSection | ヘッダーやフッターなどのフルハイト以外のセクション用のCSSセレクター。 |
easing | イージングメソッドを定義します。 |
scrollSpeed | スクロールのスピードの値。ミリ秒で設定します。 |
offset | 各セクションの位置をオフセットするピクセル単位の距離。 |
scrollbars | スクロールバーを表示するかどうかを定義するブール値。 |
standardScrollElements | 標準スクロール動作を必要とするセクション内の要素のCSSセレクタ。 |
setHeights | Scollifyがセクションに高さを割り当てるかどうかを定義するブール値。 デフォルトではTrueです。 |
overflowScroll | Scrollifyでセクション内のオーバーフローコンテンツのスクロールを許可するかどうかを定義するブール値。 デフォルトではTrueです。 |
updateHash | セクションをスクロールするときにScrollifyがブラウザの位置ハッシュを更新するかどうかを定義するブール値。 デフォルトではTrueです。 |
touchScroll | Scrollifyがタッチスクロールイベントを処理するかどうかを定義するブール値です。 デフォルトではTrueです。 |
before | セクションがmoveメソッドを使用してスクロールされる前に発生するコールバック。 引数には、セクションのインデックスとすべてのセクション要素の配列が含まれます。 |
after | 新しいセクションがスクロールされた後に起動されるコールバック。 引数には、セクションのインデックスとすべてのセクション要素の配列が含まれます。 |
afterResize | ウィンドウがサイズ変更された後に起動されるコールバック。 |
afterRender | Scrollifyの初期化後に起動されるコールバックです。 |
補足
sectionName
データ属性の名前を変更します。デフォルトは「data-section-name」ですが、それを変更したい場合は設定します。
scrollbars
こちらを「scrollbars:false」にするとスクロールバーが消えますが、「overflowScroll:false」としたのと同様になり、オーバーフローコンテンツのスクロールができなくなりますので注意。
setHeights
先ほど触れましたが、デフォルトだとセクションの高さがブラウザの高さより低い場合はブラウザの高さに自動で合わせてくれます
「setHeights:false」で高さを設定しなくなります。
updateHash
「updateHash:false」にするとURL末尾に「#○○」がつかなくなります。
メソッド
次にメソッドを見ていきましょう。
$.scrollify.move(“#name”); | moveメソッドを使用すると、特定のセクションにスクロールすることができます。 これは、セクションのインデックス、またはハッシュが前に置かれたセクションの名前を取ることができます。 |
---|---|
$.scrollify.instantMove(“#name”); | instantMoveメソッドは、アニメーションなしで特定のセクションにスクロールするために使用できます。 セクションのインデックス、またはハッシュが前に置かれたセクションの名前を解析できます。 |
$.scrollify.next(); | nextのメソッドは、現在のパネルの直後にあるパネルにスクロールするために使用できます。 |
$.scrollify.previous(); | previousのメソッドを使用すると、現在のパネルの直前にあるパネルにスクロールできます。 |
$.scrollify.instantNext(); | instantNextメソッドは、現在のパネルの直後にあるアニメーションなしのパネルにスクロールするために使用できます。 |
$.scrollify.instantPrevious(); | instantPreviousメソッドは、現在のパネルの直前のパネルにスクロールするために使用できます。 |
$.scrollify.destroy(); | destroyメソッドは、すべてのScrollifyイベントを削除し、パネルからセット高さを削除します。 |
$.scrollify.update(); | updateメソッドは、パネルの高さと位置を再計算します。 |
$.scrollify.current(); | currentのメソッドは、現在のセクションをjQueryオブジェクトとして返します。 |
$.scrollify.disable(); | disableメソッドは、スクロールスナップ動作をオフにして、ページを通常のようにスクロールします。 |
$.scrollify.enable(); | enableメソッドは、disableメソッドが使用された後、スクロールスナップ動作を再開します。 |
$.scrollify.isDisabled(); | isDisabledメソッドは、Scrollifyが現在無効になっている場合はtrueを返し、そうでない場合はfalseを返します。 |
$.scrollify.setOptions(); | setOptionsメソッドを使用して、初期化オプションのいずれかを変更できます。 オプションオブジェクトを解析するだけです。 |
応用1 ページネーション
ではメソッドも確認したところで応用編をやっていきます。公式のデモにもありますが「ページネーション」をつけます。
HTMLは変更なしです。
CSS
.pagenation{
padding: 20px;
position: fixed;
right: 0;
top: 50%;
}
.pagenation li{
list-style-type: none;
margin-bottom: 20px;
}
.pagenation a{
display: block;
height: 10px;
border: 1px solid #000;
width: 10px;
}
.pagenation a.active{
background: #000;
}
CSSはこの後、jQueryで追加する「pagenation」のスタイルを追加しました。
jQuery
var current;
$.scrollify({
section:".box",
setHeights:false,
scrollbars:false,
before:function(i,box){
current = i
$('.pagenation .active').removeClass('active');
$('.pagenation').find('a').eq(i).addClass('active');
},
afterRender:function(){
var pagenation = '<ul class="pagenation">';
$('.box').each(function(i){
pagenation += '<li><a></a></li>';
});
pagenation += '</ul>';
$('body').append(pagenation);
$('.pagenation a').each(function(i){
$(this).on('click',function(){
$.scrollify.move(i);
});
});
$('.pagenation li:first-child').find('a').addClass('active');
},
});
$(window).on('resize',function(){
if(current){
var currentScrl = $('.box').eq(current).offset().top;
$(window).scrollTop(currentScrl);
}
});
11行目
「afterRender」内でページネーションを作っていきます。「afterRender」はロードされた後の初期化後に1度だけ発生します。
20行目
作ったページネーションのaタグをクリックしたら、「$.scrollify.move」でページネーションと同じ番号のセクションに移動します。
23行目
ページネーションの一番最初に「active」クラスをつけています。
8,9行目
「before」でページネーションの「active」クラスを現在の位置に更新しています。「before」はスクロールの前に発生しますが、途中までスクロールしている際のリロードでも「before」は発生します。
応用2 レイヤードスクロール
サンプルをもう1つ。こちらも公式にサンプルがありますが、やってみたかったので作りました。せっかくなので先ほどのページネーションは活かしたままやっていきます。
こちらはCSSの「position:fixed;」で固定表示したコンテンツを前面に置いて、スクロールのイベントを発火点にクラスを付けたり外したりして、表示するコンテンツを切り替えるというものです。では見ていきましょう。
HTML
<div class="fixed-area">
<div class="fixed-area__inner">
<div class="fixed-area__inner__contents js-slide">
<h2 class="fixed-area__inner__contents__title">Layered scrolling1</h2>
<p>
In this example, sections act as a scrolling background layer while foreground content stays in a fixed position.
</p>
</div><!--fixed-area__inner__contents-->
<!--以下省略-->
</div><!--fixed-contents__inner-->
</div><!--fixed-contents-->
<div class="box box1">
<div class="box__inner box1__inner">
<h2>box1</h2>
</div><!--box__inner box1__inner-->
</div><!--box-->
<!--以下省略-->
1行目
固定表示する部分です。
3行目
「js-slide」クラスがjQueryでクラスを付けたり外したりする部分です。以降、同じものが続くのでHTMLコードは省略します。
CSS
.fixed-area{
color: #fff;
position: fixed;
top: 100px;
width: 100%;
z-index: 99;
}
.fixed-area__inner{
position: relative;
margin: 0 auto;
width: 600px;
}
.fixed-area__inner__contents{
opacity: 0;
position: absolute;
top: 60px;
transition: 1s;
}
.fixed-area__inner__contents.active{
opacity: 1;
top: 0;
}
.fixed-area__inner__contents__title{
font-size: 50px;
}
.box{
color: #fff;
height: 600vh;
}
.box__inner{
background: rgba(0,0,0,0.5);
height: 100vh;
padding: 40px;
}
1〜18行目
固定表示部分のスタイルを追加しています。
19行目
この後のjQueryで「active」クラスを付け外しして表示を切り替えます。
28行目
公式ではjQueryで高さを設定してますが私はCSSでやります。ブラウザの高さの6倍に設定します。
最初は公式の、背景が遅れて来るやり方がかわからなかったのですが、セクション要素をブラウザの高さ6倍にすることで距離を取って実現していることがわかりました。なるほどね。
32行目
これで「.box」はブラウザの高さ6倍だけど、「.box__inner」は「height: 100vh;」でブラウザの高さに合わせてるので、遅れてくるような表現ができます。
jQuery
var current;
$.scrollify({
section:".box",
scrollSpeed:1100,
setHeights:false,
scrollbars:false,
easing:"easeOutQuad",
overflowScroll:false,
before:function(i,box){
current = i
$('.pagenation .active').removeClass('active');
$('.pagenation').find('a').eq(i).addClass('active');
$('.js-slide.active').removeClass('active');
$('.js-slide').eq(i).addClass('active');
},
afterRender:function(){
var pagenation = '<ul class="pagenation">';
$('.box').each(function(i){
pagenation += '<li><a></a></li>';
});
pagenation += '</ul>';
$('body').append(pagenation);
$('.pagenation a').each(function(i){
$(this).on('click',function(){
$.scrollify.move(i);
});
});
$('.pagenation li:first-child').find('a').addClass('active');
$('.js-slide:first-child').addClass('active');
},
});
$(window).on('resize',function(){
if(current){
var currentScrl = $('.box').eq(current).offset().top;
$(window).scrollTop(currentScrl);
}
});
8行目
「.box」の高さをブラウザの6倍にしていますのでオーバーフロー部分をスクロールさせないようにします。
31行目
初期化時に一番最初の「js-slide」に「active」クラスをつけて表示しています。
14,15行目
ページネーションと同様に、スクロールをきっかけにして「js-slide」から「active」クラスを外し、現在表示するセクションの「js-slide」に「active」クラスを付け直して更新しています。
まとめ
「jQuery Scrollify」はとても使いやすいプラグインでした。注意することは、スクロールというユーザーの操作に関わることを実装する際は、「メリット」、「デメリット」を踏まえた上で採用するか検討しましょう。
素晴らしいプラグイン「jQuery Scrollify」の開発者に感謝です。