ロードアニメーション表示中のスクロールをJavaScriptで禁止する方法

Webサイトやアプリケーションで、コンテンツの読み込み中にロードアニメーションを表示することは、ユーザー体験を向上させるための一般的な手法です。しかし、アニメーションが表示されている間にユーザーがスクロールできてしまうと、意図しないレイアウト崩れが起きたり、読み込み完了後にページのトップにいない、といった問題が発生する可能性があります。

この記事では、JavaScriptを使用して、ロードアニメーションが表示されている間だけスクロールを完全に禁止し、読み込み完了後に自動で解除する方法を、コードの詳しい解説と具体的な実装例を交えて紹介します。

なぜスクロールの禁止が必要か?

  1. ユーザー体験の維持: ユーザーをページのトップに留めることで、コンテンツが完全に表示されたときに、意図した通りのファーストビューを見せることができます。
  2. レイアウト崩れの防止: 読み込み途中の不完全な状態でスクロールされることによる、表示の崩れやガタつきを防ぎます。
  3. 意図した操作への誘導: ローディング中は操作を制限することで、ユーザーに「現在読み込み中である」ことを明確に伝え、コンテンツの準備が整うまで待ってもらうことができます。

実装コード全体

まずは、基本のコードになります。

// スクロールを禁止する関数
function disable_scroll(event) {
  event.preventDefault();
}

// スクロール禁止イベントを設定
document.addEventListener('touchmove', disable_scroll, { passive: false });
document.addEventListener('mousewheel', disable_scroll, { passive: false });

// ページの読み込みが完了したら、スクロール禁止を解除する
function enable_scroll(){
    document.removeEventListener('touchmove', disable_scroll, { passive: false });
    document.removeEventListener('mousewheel', disable_scroll, { passive: false });
}

window.addEventListener('load', () => {
    // 読み込み完了時に実行したい処理をここに書く
    // 例:ローディング画面を非表示にするなど

    // スクロール禁止を解除
    enable_scroll();
});
JavaScript

コードの詳細解説

上記のコードが何をしているのか、一つずつ解説していきます。

1. スクロールを禁止する disable_scroll 関数

function disable_scroll(event) {
  event.preventDefault();
}
JavaScript

これはスクロール禁止処理の核となる関数です。event.preventDefault()は、イベント(この場合はtouchmovemousewheel)に紐づくブラウザのデフォルトの動作をキャンセルするメソッドです。つまり、マウスホイールを回したり、画面をタッチしてスワイプしたときの「スクロールする」という標準の動きを無効化します。

2. スクロールイベントの監視

document.addEventListener('touchmove', disable_scroll, { passive: false });
document.addEventListener('mousewheel', disable_scroll, { passive: false });
JavaScript

ここでは、addEventListenerを使って、スクロールに関連するイベントを監視(リッスン)します。

  • touchmove: スマートフォンやタブレットなどのタッチデバイスで、画面に触れたまま指を動かしたときに発生します。
  • mousewheel: PCでマウスホイールを操作したときに発生します。

これらのイベントが発生するたびに、先ほど定義したdisable_scroll関数が呼び出され、スクロールがキャンセルされます。

{ passive: false } の重要性

このオプションは非常に重要です。近年のブラウザは、スクロールパフォーマンスを最適化するため、スクロール関連のイベントリスナーをデフォルトでpassive: trueとして扱います。これは、「イベントリスナー内でpreventDefault()を呼びません」とブラウザに約束するようなもので、ブラウザはリスナーの処理を待たずにスクロールを開始できます。

しかし、今回はpreventDefault()を使いたいので、passive: falseを明示的に指定して、「preventDefault()を呼び出す可能性があります」とブラウザに伝える必要があります。これを指定しないと、preventDefault()が無視され、スクロール禁止が機能しない場合があります。

3. スクロール禁止を解除する enable_scroll 関数

function enable_scroll(){
    document.removeEventListener('touchmove', disable_scroll, { passive: false });
    document.removeEventListener('mousewheel', disable_scroll, { passive: false });
}
JavaScript

この関数は、addEventListenerで登録したイベントリスナーを解除する役割を持ちます。removeEventListenerを使うことで、disable_scroll関数が呼び出されなくなり、ブラウザの標準のスクロール機能が再び有効になります。

4. ページの読み込み完了を待つ

window.addEventListener('load', () => {
    // ...
    enable_scroll();
});
JavaScript

windowloadイベントは、HTMLの解析だけでなく、ページに含まれるすべてのリソース(画像、CSS、スクリプトなど)の読み込みが完了した時点で発生します。ロードアニメーションは、まさにこの「すべての準備が整う」までのつなぎとして表示されるため、loadイベントはスクロール禁止を解除するのに最適なタイミングです。

loadイベントが発生したら、enable_scroll関数を呼び出して、ユーザーが自由にスクロールできるようにします。

実装例:ローディング画面と組み合わせる

それでは、実際にローディング画面と組み合わせて、このスクロール禁止機能を実装してみましょう。

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ロード中のスクロール禁止デモ</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>

    <!-- ローディング画面 -->
    <div id="loader">
        <p>Loading...</p>
    </div>

    <!-- メインコンテンツ -->
    <div id="content">
        <h1>ようこそ!</h1>
        <p>このページはロード完了後に表示されます。</p>
        <!-- 長いコンテンツでスクロールを発生させる -->
        <div style="height: 2000px; background: #f0f0f0; padding: 20px;">
            スクロール用の領域
        </div>
    </div>

    <script src="script.js"></script>
</body>
</html>
HTML

CSS (style.css)

body {
    margin: 0;
    font-family: sans-serif;
}

/* ローディング画面のスタイル */
#loader {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 2rem;
    z-index: 1000;
    transition: opacity 0.5s;
}

/* メインコンテンツは最初は非表示 */
#content {
    display: none;
}
CSS

JavaScript (script.js)

// --- スクロール禁止のコード ---

// スクロールを禁止する関数
function disable_scroll(event) {
  event.preventDefault();
}

// スクロール禁止イベントを設定
document.addEventListener('touchmove', disable_scroll, { passive: false });
document.addEventListener('mousewheel', disable_scroll, { passive: false });

// スクロール禁止を解除する関数
function enable_scroll(){
    document.removeEventListener('touchmove', disable_scroll, { passive: false });
    document.removeEventListener('mousewheel', disable_scroll, { passive: false });
}


// --- ページの読み込み完了時の処理 ---

window.addEventListener('load', () => {
    const loader = document.getElementById('loader');
    const content = document.getElementById('content');

    // ローディング画面をフェードアウト
    loader.style.opacity = '0';

    // アニメーションが終わったらloaderを非表示にし、コンテンツを表示
    setTimeout(() => {
        loader.style.display = 'none';
        content.style.display = 'block';
    }, 500); // 0.5秒後に実行

    // スクロール禁止を解除
    enable_scroll();

    // 念のためページのトップにスクロール
    window.scrollTo(0, 0);
});
JavaScript

まとめ

ロードアニメーション中のスクロール禁止は、ささいなことのように思えるかもしれませんが、ユーザーにストレスを与えず、意図した通りのWebサイトを体験してもらうための重要な配慮です。

  • event.preventDefault()でスクロールのデフォルト動作を止める。
  • touchmove(SP)とmousewheel(PC)の両方のイベントに対応する。
  • preventDefaultを確実に機能させるため{ passive: false }を指定する。
  • window.addEventListener('load', ...)を使い、ページの全リソース読み込み完了後にスクロール禁止を解除する。

これらのポイントを押さえることで、よりプロフェッショナルで完成度の高いWebサイトを構築することができます。

read next