はじめに
画面いっぱいに1枚ずつセクションが切り替わっていく、あの「フルスクリーンスクロール」の演出。ポートフォリオサイトやプロダクトのランディングページで見かけたことがある方も多いと思います。あれを自前で実装しようとすると、スクロール量の検知、セクションの位置合わせ、慣性スクロールのキャンセル、タッチデバイス対応と、地味に面倒な処理が積み重なります。
fullPage.jsは、その面倒な部分をまるごと肩代わりしてくれるJavaScriptライブラリです。HTML側にdivを並べてオプションを渡すだけで、あの1枚ずつめくれていくスクロール演出が動き出します。
なお、fullPage.jsはGPLv3または商用のライセンス体系で、ライセンスキーなしで動かすとコンソールに警告が出て「Made with fullPage.js」のクレジットが強制表示されます。そのため、この記事では他の記事のように埋め込みで動かす形は取らず、手元にコピーしてすぐ試せるコード一式を載せています。
fullPage.jsとは
fullPage.jsは、「Create full screen pages fast and simple」を掲げるJavaScriptライブラリで、縦方向にセクションを1枚ずつ切り替えるフルスクリーンスクロールサイトを作成できます。jQuery版とバニラJS版の両方が提供されていますが、現行のv4系はjQueryなしでも動作するのが特徴です。
各セクションの中にさらに横方向のスライドを組み込むこともでき、キーボード操作・タッチ操作・マウスホイールにひととおり対応しています。
主な特徴
- セクション単位のフルスクリーンスクロール -
#fullpage配下に.sectionを並べるだけで、1画面ずつ切り替わるスクロールが実現します - jQuery非依存 - v4系はバニラJavaScriptとして動作し、
new fullpage(...)で初期化できます - アンカー・メニュー連動 -
anchorsオプションでURLハッシュに対応し、menuオプションでナビゲーションメニューのアクティブ表示を自動化できます - セクション内スライド -
.sectionの中に.slideを並べると、そのセクションだけ横スライド式のコンテンツになります - 豊富なコールバック -
afterLoadやonLeaveなど、セクション切り替えのタイミングで処理を挟めます - ライセンス体系に注意 - GPLv3準拠のオープンソースプロジェクトであれば無料で使えますが、クレジット表示(fullPage.js使用の明示)が必須です。クレジットを外したい場合や非オープンソースの商用プロジェクトで使う場合は、コマーシャルライセンスの購入が必要になります
最後の点は、このブログで紹介してきたMITライセンスのライブラリとは毛色が違うので、導入前に必ず確認しておきたいところです。
インストール
npmから通常のパッケージとしてインストールできます。
npm install fullpage.js
ビルド環境を用意せず手早く試したい場合は、CDN経由でCSSとJSを読み込む方法もあります。
<link rel="stylesheet" href="https://unpkg.com/fullpage.js@4.0.41/dist/fullpage.min.css">
<script src="https://unpkg.com/fullpage.js@4.0.41/dist/fullpage.min.js"></script>
ES modules環境であれば、CSSとJSをそれぞれimportして使います。
import fullpage from 'fullpage.js'
import 'fullpage.js/dist/fullpage.min.css'
fullPage.jsのサンプルコード
fullPage.jsの基本は、#fullpage要素の中に.sectionを並べ、new fullpage('#fullpage', options)で初期化することです。次のサンプルではnavigationオプションでドット式のナビゲーションを表示し、afterLoadコールバックでセクションが切り替わるたびに現在の位置をコンソールへ出力しています。
HTML・CSS・JavaScriptの3つをそのままコピーすれば、手元ですぐ動かせます。マウスホイールでスクロールするか、右側のナビゲーションドットをクリックするとセクションが切り替わります。
<div id="fullpage">
<div class="section" id="section1">
<h2>Section 1</h2>
</div>
<div class="section" id="section2">
<h2>Section 2</h2>
</div>
<div class="section" id="section3">
<h2>Section 3</h2>
</div>
</div>
@import url('https://unpkg.com/fullpage.js@4.0.41/dist/fullpage.min.css');
body { margin: 0; font-family: system-ui, sans-serif; }
.section {
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 28px;
}
#section1 { background: #2563eb; }
#section2 { background: #16a34a; }
#section3 { background: #dc2626; }
import fullpage from 'fullpage.js'
new fullpage('#fullpage', {
autoScrolling: true,
navigation: true,
navigationTooltips: ['はじめ', 'なか', 'おわり'],
scrollingSpeed: 700,
afterLoad: (origin, destination) => {
console.log('現在のセクション:', destination.index + 1)
},
})
autoScrolling: trueにすると、スクロールの途中で止まらず必ずセクション単位でスナップします。navigation: trueをfalseに変えるとドットが消え、代わりにスクロールやキーボードの矢印キーだけで移動する形になります。afterLoadは「セクションが表示され終わったタイミング」で呼ばれるコールバックで、destination.indexから今どのセクションにいるかが分かります。
基本的な使い方
最小構成であれば、HTMLとJavaScriptあわせて数行で動きます。
<div id="fullpage">
<div class="section">セクション1</div>
<div class="section">セクション2</div>
<div class="section">セクション3</div>
</div>
import fullpage from 'fullpage.js'
new fullpage('#fullpage', {
autoScrolling: true,
scrollingSpeed: 700,
})
#fullpageの直下に.sectionクラスの要素を並べるだけで、fullPage.js側が自動的に各セクションの高さをビューポート全体に合わせてくれます。CSSファイル(fullpage.min.css)の読み込みを忘れると、位置合わせのスタイルが当たらず正しく動作しない点だけ注意してください。
実践的なユースケース
アンカーとメニューを連動させる
セクションごとにURLを分けたい、あるいは固定ヘッダーのメニューからジャンプできるようにしたい、というのはフルスクリーンサイトでよくある要件です。fullPage.jsではanchorsオプションで各セクションにURLハッシュ(#homeなど)を割り当て、menuオプションでナビゲーション要素を指定するだけで、クリック時のスクロールと現在地に応じたアクティブクラスの付け替えが自動化されます。
<nav id="menu">
<a href="#home" class="active">Home</a>
<a href="#about">About</a>
<a href="#contact">Contact</a>
</nav>
<div id="fullpage">
<div class="section" data-anchor="home" id="s-home"><h2>Home</h2></div>
<div class="section" data-anchor="about" id="s-about"><h2>About</h2></div>
<div class="section" data-anchor="contact" id="s-contact"><h2>Contact</h2></div>
</div>
@import url('https://unpkg.com/fullpage.js@4.0.41/dist/fullpage.min.css');
body { margin: 0; font-family: system-ui, sans-serif; }
#menu {
position: fixed; top: 12px; left: 50%; transform: translateX(-50%);
z-index: 100; display: flex; gap: 16px; background: #fff;
padding: 8px 16px; border-radius: 999px; box-shadow: 0 2px 8px rgba(0,0,0,.15);
}
#menu a { color: #333; text-decoration: none; font-size: 14px; }
#menu a.active { color: #2563eb; font-weight: bold; }
.section { display: flex; align-items: center; justify-content: center; color: #fff; }
#s-home { background: #0ea5e9; }
#s-about { background: #a855f7; }
#s-contact { background: #f97316; }
import fullpage from 'fullpage.js'
new fullpage('#fullpage', {
anchors: ['home', 'about', 'contact'],
menu: '#menu',
navigation: false,
afterLoad: (origin, destination) => {
console.log('アンカー:', destination.anchor)
},
})
メニューのリンクをクリックすると、anchorsで登録した文字列に対応するセクションまでスクロールし、menuで指定した要素内のリンクへ自動的にactiveクラスが付け替わります。anchorsの配列の並び順を変えると、URLハッシュとセクションの対応関係もそのまま入れ替わります。
セクション内に横スライドを組み込む
縦方向のセクションだけでなく、特定のセクションの中でギャラリーやステップ紹介のような横スクロールを見せたいケースもあります。.sectionの中に.slide要素を並べると、そのセクションだけ横方向のスライドショーになります。controlArrowsで左右の矢印を表示し、slidesNavigationでスライド用のドットも追加できます。
<div id="fullpage">
<div class="section" id="top"><h2>上にスクロール</h2></div>
<div class="section">
<div class="slide" id="slide1"><h2>Slide 1</h2></div>
<div class="slide" id="slide2"><h2>Slide 2</h2></div>
<div class="slide" id="slide3"><h2>Slide 3</h2></div>
</div>
<div class="section" id="bottom"><h2>下にスクロール</h2></div>
</div>
@import url('https://unpkg.com/fullpage.js@4.0.41/dist/fullpage.min.css');
body { margin: 0; font-family: system-ui, sans-serif; }
.section, .slide { display: flex; align-items: center; justify-content: center; color: #fff; }
#top { background: #334155; }
#bottom { background: #334155; }
#slide1 { background: #059669; }
#slide2 { background: #0891b2; }
#slide3 { background: #7c3aed; }
import fullpage from 'fullpage.js'
new fullpage('#fullpage', {
autoScrolling: true,
controlArrows: true,
slidesNavigation: true,
slidesNavPosition: 'bottom',
})
真ん中のセクションだけ、マウスホイールの縦スクロールが横方向のスライド送りに変換されます。すべての.slideを見終わってから、さらにホイールを回すと次のセクションへ縦に移動する仕組みです。controlArrows: falseにすると矢印が消え、キーボードの左右キーとスワイプだけでスライドを送る形になります。
JavaScript APIで外部ボタンから任意のセクションへ移動する
ナビゲーションドットやスワイプ以外に、独自に配置した「次へ」ボタンや目次リンクからセクション移動を制御したい場合もあります。new fullpage(...)が返すインスタンスにはmoveSectionUp() / moveSectionDown() / moveTo()といったメソッドが生えているので、#fullpageの外にあるボタンからでも自由に操作できます。
<div id="controls">
<button id="prev">▲ 前へ</button>
<button id="next">▼ 次へ</button>
<button id="jump3">3番目へジャンプ</button>
</div>
<div id="fullpage">
<div class="section" id="p1"><h2>Section 1</h2></div>
<div class="section" id="p2"><h2>Section 2</h2></div>
<div class="section" id="p3"><h2>Section 3</h2></div>
</div>
@import url('https://unpkg.com/fullpage.js@4.0.41/dist/fullpage.min.css');
body { margin: 0; font-family: system-ui, sans-serif; }
#controls {
position: fixed; top: 12px; right: 12px; z-index: 100;
display: flex; flex-direction: column; gap: 6px;
}
#controls button {
padding: 6px 12px; border: none; border-radius: 6px;
background: #1e293b; color: #fff; cursor: pointer; font-size: 13px;
}
.section { display: flex; align-items: center; justify-content: center; color: #fff; }
#p1 { background: #be123c; }
#p2 { background: #4d7c0f; }
#p3 { background: #1d4ed8; }
import fullpage from 'fullpage.js'
const fp = new fullpage('#fullpage', {
autoScrolling: true,
navigation: true,
})
document.getElementById('next').onclick = () => fp.moveSectionDown()
document.getElementById('prev').onclick = () => fp.moveSectionUp()
document.getElementById('jump3').onclick = () => {
console.log('3番目のセクションへジャンプします')
fp.moveTo(3)
}
右上のボタンを押せば、スクロールやドットクリックと同じ動きをコードから起動できます。moveTo(3)の引数はセクション番号(1始まり)で、anchorsを設定している場合はアンカー名の文字列(例:moveTo('contact'))も渡せます。目次コンポーネントやフォーム送信後の自動遷移など、ユーザー操作以外のタイミングでセクションを切り替えたい場面で使える書き方です。
まとめ
fullPage.jsを使うと、フルスクリーンスクロールという実装コストの高い演出を、.sectionを並べてオプションを渡すだけで再現できます。anchorsとmenuによるナビゲーション連動、.slideによる横スライド、moveTo()などのAPIによるプログラム制御と、単なる「1枚めくり」以上の作り込みにも対応できるのが分かっていただけたと思います。
一方で、GPLv3準拠でクレジット表示が必須という条件や、非オープンソースの商用利用ではコマーシャルライセンスが必要という点は、他のMITライセンスのライブラリとは異なる注意点です。ポートフォリオサイトやランディングページに取り入れる際は、まずライセンス条件を確認したうえで、サンプルのオプションを書き換えながら挙動を確かめてみてください。