JavaScriptでページのスクロールを無効化する方法7選

JavaScriptを使ったモダンなページスクロール無効化の実現JS
この記事は約21分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●JavaScriptでスクロールを無効化する方法

Webサイトを制作していると、ページ読み込み中やモーダルウィンドウ表示時など、一時的にページのスクロールを無効化したい場面に遭遇することがあります。

こうした要望に応えるには、JavaScriptやjQueryを使ってスクロール無効化を実装するのが一般的です。

でも、JavaScriptの基礎知識はあるけど実践経験が少ない、jQueryは使ったことあるけどバニラJSは自信がない…といった方も多いのではないでしょうか。

そんな初心者のみなさんでも安心してください。これからサンプルコードを交えながら、わかりやすく丁寧に解説していきますので、ぜひ最後までお付き合いください。

それでは、まずはシンプルなJavaScriptでスクロールを無効化する方法から見ていきましょう。

○サンプルコード1:JavaScriptでスクロール無効化

// スクロール無効化
function disableScroll() {
  // 現在の位置を保存
  const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
  const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;

  // スクロール位置を固定
  window.onscroll = function() {
    window.scrollTo(scrollLeft, scrollTop);
  };
}

// スクロール無効化解除
function enableScroll() {
  window.onscroll = function() {};
}

このサンプルコードでは、disableScroll()関数でスクロールを無効化し、enableScroll()関数で無効化を解除しています。

disableScroll()内では、まず現在のスクロール位置をscrollTopとscrollLeftに保存。

そしてwindow.onscrollイベントで、保存したスクロール位置にwindow.scrollTo()メソッドを使って強制的にスクロールさせることで、見かけ上スクロールを無効化しているわけです。

一方のenableScroll()は、window.onscrollに空の関数を設定することで、スクロール無効化を解除しています。

実行例

// ボタンクリックでスクロール無効化
document.getElementById('disable').addEventListener('click', disableScroll);

// 3秒後に自動的にスクロール無効化解除
setTimeout(enableScroll, 3000);

ボタンのクリックイベントでdisableScroll()を呼び出し、3秒後にsetTimeout()でenableScroll()を実行することで、一時的なスクロールの無効化と解除を実現しています。

シンプルで使いやすいサンプルコードですが、jQueryを使えばもっと簡潔に書けますよね。

次は、そんなjQueryを使ったスクロール無効化の方法を見ていきましょう。

○サンプルコード2:jQueryでスクロール無効化

// スクロール無効化
function disableScroll() {
  $('html, body').css({
    overflow: 'hidden',
    height: '100%'
  });
}

// スクロール無効化解除  
function enableScroll() {
  $('html, body').css({
    overflow: 'auto',
    height: 'auto'
  });
}

jQueryを使った場合、わずか数行でスクロールの無効化と解除が実装できました。

disableScroll()では、$(‘html, body’)でと要素を取得し、css()メソッドでCSSを設定。

overflowプロパティをhiddenにすることでスクロールバーを非表示にし、heightを100%に設定することでスクロール自体を無効化しています。

enableScroll()では、overflow: autoとheight: autoを設定して、スクロール無効化を解除しています。

実行例

// ボタンクリックでスクロール無効化
$('#disable').on('click', disableScroll);

// 3秒後に自動的にスクロール無効化解除
setTimeout(enableScroll, 3000);

こちらも先ほどと同様、ボタンクリックでdisableScroll()、3秒後にenableScroll()を呼び出して、スクロールの一時無効化を行っています。

●CSSを使ったスクロール無効化

JavaScriptやjQueryを使えば、手軽にスクロールの無効化が実装できることがわかりましたね。

でも、実はCSSだけでもスクロールを無効化することができるんです。

CSSでスクロール無効化を実現する方法には、大きく分けて2つのアプローチがあります。

1つ目は、スクロールバー自体を非表示にする方法。

2つ目は、overflow: hiddenを使ってスクロールを無効化する方法です。

それぞれのアプローチには一長一短があるので、状況に応じて使い分けるのがベストですね。

初心者のみなさんには少しわかりにくいかもしれませんが、これからサンプルコードを交えながらわかりやすく解説していきますので、ぜひ最後まで読み進めてみてください。

○サンプルコード3:CSSでスクロールバー非表示

まずは、スクロールバー自体を非表示にする方法から見ていきましょう。

/* スクロールバー非表示 */
body {
  -ms-overflow-style: none; /* IE, Edge用 */
  scrollbar-width: none; /* Firefox用 */
}

body::-webkit-scrollbar {
  display: none; /* Chrome, Safari用 */
}

このCSSコードを適用することで、ブラウザ標準のスクロールバーが非表示になります。

-ms-overflow-styleプロパティとscrollbar-widthプロパティは、それぞれIE/EdgeとFirefox用のスクロールバー非表示設定。

::-webkit-scrollbarセレクタは、ChromeやSafariなどのWebKit系ブラウザでスクロールバーを消すために使用します。

実行結果としては、スクロールバーが非表示になり、見た目上はスクロールできないように見えます。

ただし、マウスホイールやキーボードでのスクロールは可能なので注意が必要です。

スクロールバーを消すだけならこの方法でOKですが、スクロール自体を完全に無効化したい場合は、overflow: hiddenを使う方法の方が適しています。

○サンプルコード4:overflow:hiddenの使用例

/* スクロール無効化 */
html, body {
  overflow: hidden;
  height: 100%;
}

htmlとbody要素に対して、overflowプロパティをhiddenに、heightを100%に設定するだけ。

これだけでページ全体のスクロールが無効化されます。

実行結果としては、マウスホイールやキーボードでのスクロールが効かなくなり、ページが固定されます。

スマートフォンなど、タッチ操作の端末でも同様に機能するため、汎用性の高い方法だと言えますね。

ただ、ページ全体のスクロールを無効にすると、コンテンツが隠れてしまう可能性もあるので、全体ではなく特定の要素だけスクロールを無効化したい場合もあるでしょう。

そんな時は、次章で紹介する方法を使ってみてください。

●特定の要素のスクロールを無効化

CSSを使えば、ページ全体だけでなく特定の要素のスクロールも簡単に無効化できます。

例えば、divやiframeなどの要素内のスクロールを止めたいケースってありますよね。

そんな時は、該当する要素にoverflow: hiddenを設定するだけ。

これで要素内のスクロールバーが非表示になり、スクロールも無効化されます。

でも、実際にコードを書く時には、要素の構造や振る舞いに応じて細かな調整が必要になるんです。

初心者のみなさんには少し難しいかもしれませんが、一緒にサンプルコードを見ながら理解を深めていきましょう。

○サンプルコード5:divのスクロール無効化

まずは、div要素のスクロールを無効化する方法から見ていきましょう。

<div class="scrollable">
  <p>スクロール可能なコンテンツ</p>
  <p>...</p>
</div>

<div class="non-scrollable">  
  <p>スクロール不可なコンテンツ</p>
  <p>...</p>
</div>
.scrollable {
  width: 300px;
  height: 200px;
  overflow: auto;
}

.non-scrollable {
  width: 300px;  
  height: 200px;
  overflow: hidden;
}

overflow: autoを設定した.scrollableクラスのdivは、コンテンツがはみ出した時にスクロールバーが表示され、スクロールが可能になります。

一方、overflow: hiddenを設定した.non-scrollableクラスのdivは、コンテンツがはみ出してもスクロールバーが現れず、スクロールも無効化されるわけです。

実行結果として、.scrollableクラスのdivはスクロール可能で、.non-scrollableクラスのdivはスクロールが無効化され、はみ出したコンテンツは非表示になります。

ただ、この方法だとはみ出したコンテンツが見えなくなってしまうので、注意が必要ですね。

コンテンツ量に応じてdivのサイズを適切に設定するか、スクロールの代わりにページネーションを用意するなどの工夫が求められます。

○サンプルコード6:iframeのスクロール無効化

iframeのスクロール無効化も、基本的にはdivと同じ方法で実現できます。

<iframe class="scrollable" src="scrollable-page.html"></iframe>

<iframe class="non-scrollable" src="scrollable-page.html"></iframe>
.scrollable {
  width: 100%;
  height: 300px; 
}

.non-scrollable {
  width: 100%;
  height: 300px;
  overflow: hidden;
}

iframeの場合、width: 100%を指定して親要素の幅に合わせつつ、heightで高さを明示的に指定するのがポイント。

その上で、overflow: hiddenを設定することでiframe内のスクロールが無効化されます。

実行結果として、.scrollableクラスのiframeは内部コンテンツに応じてスクロール可能になりますが、.non-scrollableクラスのiframeはスクロールバーが表示されず、はみ出た部分は非表示になります。

iframe内のページを全て見せたい場合は、heightをautoにするか、iframeのサイズをJavaScriptで動的に調整する必要がありますね。

状況に応じて適切な方法を選択しましょう。

●スマートフォンのスクロール無効化

これまではPC向けのスクロール無効化テクニックを中心に見てきましたが、スマートフォンの場合はちょっと事情が異なります。

特にiOSとAndroidでは、スクロール動作の仕組みが微妙に違うんです。

スマホサイトやWebアプリを作る時は、こうしたプラットフォームの特性を踏まえた上で、適切な無効化の方法を選ぶ必要があります。

でも正直なところ、モバイル端末でのスクロール制御って、PCよりも少し難しいんですよね。

JavaScriptやCSSだけでは思い通りにいかないケースも多く、ネイティブアプリのようなスムーズな動作を実現するには、コツがいります。

初心者にとっては少し難易度が高い内容かもしれませんが、これからサンプルコードと一緒に、iOS・Android別の対策を詳しく解説していきますので、ぜひトライしてみてください。

○サンプルコード7:iOS向けスクロール無効化

まずはiOS向けの方法から見ていきましょう。

iOSでは、CSSのoverflow: hiddenを使うだけでは、うまくスクロールを無効化できない場合があります。

そこで、touchmoveイベントをJavaScriptで制御する必要があるんです。

// iOS向けスクロール無効化
document.addEventListener('touchmove', disableScroll, { passive: false });

function disableScroll(event) {
  event.preventDefault();
}

// スクロール無効化解除
document.removeEventListener('touchmove', disableScroll, { passive: false });

ポイントは、addEventListenerの第3引数に{ passive: false }を指定すること。

これにより、preventDefault()が確実に機能するようになります。

touchmoveイベントが発生すると、disableScroll関数が呼び出され、event.preventDefault()によってスクロールがキャンセルされるわけです。

スクロールを再び有効にしたい時は、removeEventListenerdisableScroll関数を解除しましょう。

実行結果として、iOSのSafariやChromeで、ページのスクロールが完全に無効化されます。

ただし、この方法だと他のタッチ操作も一緒にブロックされてしまうので、注意が必要ですね。

○サンプルコード8:Android向けスクロール無効化

続いて、Android向けの方法を見てみましょう。

Androidの場合は、iOSとは少し違ったアプローチが必要になります。

// Android向けスクロール無効化
document.addEventListener('touchstart', preventScroll, { passive: false });

function preventScroll(event) {
  if (event.touches.length > 1) {
    event.preventDefault();
  }
}

// スクロール無効化解除
document.removeEventListener('touchstart', preventScroll, { passive: false });

Androidでは、touchstartイベントを監視し、touchesプロパティの配列長が1より大きい場合にpreventDefault()を呼び出すことで、スクロールを無効化しています。

つまり、マルチタッチ操作の時だけスクロールをブロックするわけですね。

実行結果として、Android端末のChromeなどで、2本指以上のタッチ操作によるスクロールが無効化されます。

ただ、1本指のスクロールは止められないので、完全な無効化は難しいかもしれません。

モバイル端末でスクロールを無効にする時は、ユーザビリティへの影響をよく考えて、必要最小限の範囲で適用することが大切です。

長いページの場合は、むやみにスクロールを止めるのではなく、コンテンツを分割したり、ページ内リンクを設置したりするなどの工夫も必要です。

●よくあるエラーと対処法

スクロール無効化の方法はいくつか見てきましたが、実際にコードを書いていると思わぬエラーに遭遇することもありますよね。

特に、JavaScriptやjQueryに慣れていない初心者の方は、コードが意図通りに動かなくて戸惑ってしまうこともあるでしょう。

ただ、エラーはつきものですし、失敗を恐れずにチャレンジすることが大切です。

ここではスクロール無効化に関する典型的なエラーを取り上げて、その原因と対処法を詳しく解説していきます。

サンプルコードを参考にしながら、ぜひ自分でもコードを書いて試してみてください。

エラーを克服することで、JavaScriptやjQueryの理解もぐっと深まるはずですよ。

○スクロールが無効化されない場合

スクロールの無効化がうまくいかない、よくあるパターンの1つが、CSSやJavaScriptのセレクタが間違っているケースです。

例えば、次のようなコードがあったとします。

// 間違ったセレクタの例
$('.target-element').on('touchmove', function(e) {
  e.preventDefault();
});
<div id="target-element">
  スクロールを無効化したい要素
</div>

ここでは、jQueryのセレクタが.target-elementとなっていますが、HTMLの要素にはid="target-element"が設定されています。

この場合、正しいセレクタは#target-elementですね。

実行結果として、セレクタが間違っているため、スクロールの無効化が機能しません。

対処法としては、HTMLとJavaScriptのセレクタを確認し、必要に応じて修正することです。

id属性なら#class属性なら.を使うように気をつけましょう。

○スクロール無効化を解除したい

スクロールを無効化した後、ある条件でスクロールを再び有効にしたいこともあるでしょう。

でも、うっかり解除し忘れて、ページ全体がスクロールできなくなってしまった…なんてことも。

例えば、こんなコードだとします。

// スクロール無効化
$('body').on('touchmove', function(e) {
  e.preventDefault();
});

// スクロール無効化を解除(間違い)
$('body').off('touchmove');

ここでは、onメソッドでスクロールを無効化した後、offメソッドで無効化を解除しようとしています。

しかし、offメソッドの使い方が誤っています。

実行結果として、offメソッドの引数が不足しているため、スクロールの無効化が解除されません。

正しくは、次のようにイベントハンドラ関数も指定する必要があります。

// スクロール無効化を解除(正解)
$('body').off('touchmove', function(e) {
  e.preventDefault();
});

このように、onメソッドとoffメソッドではイベントハンドラ関数の指定方法が異なることに注意しましょう。

コードをコピペするときも、よく内容を確認することが大切ですね。

○特定のブラウザで機能しない

スクロールの無効化がブラウザによって機能しないこともあります。

例えば、iOSのSafariではCSSのoverflow: hiddenだけでは効果がない場合があるんです。

こんなコードを書いたとします。

/* スクロール無効化 */
body {
  overflow: hidden;
}

実行結果として、iOSのSafariでは、overflow: hiddenを設定してもスクロールが無効化されないことがあります。

こういった場合は、JavaScriptを使って個別に対応する必要があります。

先ほど紹介したiOS向けのサンプルコードを使えば、Safariでもスクロール無効化が可能です。

// iOS向けスクロール無効化
document.addEventListener('touchmove', function(e) {
  e.preventDefault();
}, { passive: false });

ブラウザごとの癖に悩まされることもありますが、諦めずに適切な対処法を探してみてください。

面倒に感じるかもしれませんが、こうした経験が積み重なることでフロントエンドの技術力は確実に向上していきます。

●スクロール無効化の応用例

スクロール無効化の基本が身に付いてきたところで、実際のWebサイトでの応用例を見ていきましょう。

ローディング画面やモーダルウィンドウ、フォーム、ページ内リンクなど、スクロール制御が役立つシーンは意外と多いんです。

でも、適切な場面で適切な方法を使わないと、かえってユーザー体験を損ねてしまうこともあります。

初心者のうちは、どういったケースでスクロール無効化を使えばいいのか迷ってしまいますよね。

ここでは、よくあるユースケースを取り上げながら、それぞれの実装方法を具体的に解説していきます。

サンプルコードを参考に、ぜひ自分でも試してみてください。きっと、スクロール無効化の使いどころが見えてくるはずですよ。

○ローディング画面での無効化

Webサイトを表示する際、データの読み込みに時間がかかると、ローディング画面を表示することがありますよね。

その間、ユーザーがページをスクロールしてしまうと、レイアウトが崩れたり、意図しない動作になったりすることがあります。

こんな時は、ローディング中だけスクロールを無効化するのが効果的です。

次のようなコードを使えば実現できますよ。

// ローディング開始
function startLoading() {
  document.body.style.overflow = 'hidden';
}

// ローディング終了
function stopLoading() {
  document.body.style.overflow = 'auto';
}

// ローディング開始
startLoading();

// 3秒後にローディング終了
setTimeout(stopLoading, 3000);

ここでは、startLoading関数でCSSのoverflowプロパティをhiddenに設定し、スクロールを無効化しています。

stopLoading関数ではoverflowautoに戻すことで、スクロールを再び有効にしています。

実行結果として、ページの読み込み中は、startLoading関数によってスクロールが無効化されます。

3秒後にstopLoading関数が呼び出され、スクロールが再び可能になります。

実際のサイトでは、APIからのデータ取得が完了した時点でローディングを終了するなど、状況に応じた制御が必要になります。

適切なタイミングでスクロールを無効化・有効化することで、ユーザーの混乱を防ぎつつスムーズな体験を実装できるでしょう。

○モーダルウィンドウ表示中の無効化

モーダルウィンドウを表示している間は、背景のコンテンツをスクロールさせたくないことがよくあります。

ユーザーの注意をモーダルに集中させるためにも、スクロール無効化は有効な手段です。

// モーダルを開く
function openModal() {
  document.getElementById('modal').style.display = 'block';
  document.body.style.overflow = 'hidden';
}

// モーダルを閉じる
function closeModal() {
  document.getElementById('modal').style.display = 'none';
  document.body.style.overflow = 'auto';
}
<button onclick="openModal()">モーダルを開く</button>

<div id="modal" style="display: none;">
  <p>モーダルウィンドウの内容</p>
  <button onclick="closeModal()">閉じる</button>
</div>

openModal関数では、モーダルウィンドウを表示すると同時にoverflow: hiddenを設定し、背景のスクロールを無効化しています。

closeModal関数ではモーダルを非表示にし、overflow: autoでスクロールを有効に戻しています。

実行結果として、「モーダルを開く」ボタンをクリックすると、モーダルウィンドウが表示され、背景のスクロールが無効になります。

モーダル内の「閉じる」ボタンをクリックすると、モーダルが閉じてスクロールが再び可能になります。

モーダル表示中のスクロール無効化は、ユーザーを適切に誘導し、意図しない操作を防ぐために欠かせない機能です。

ただし、モーダルの中身が長い場合は、モーダル内でスクロールできるようにするなど、状況に応じた柔軟な対応も必要ですね。

○フォームのオートスクロール防止

フォームの入力欄に自動フォーカスがあたると、ページが勝手にスクロールしてしまうことがあります。

特にスマートフォンでは、フォーカス時のオートスクロールが誤タップを招いたりして、ユーザーを混乱させがちです。

こういった場合は、JavaScriptでオートスクロールを防ぐのが有効です。

// フォーカス時のオートスクロールを防止
document.getElementById('input').addEventListener('focus', function(event) {
  event.preventDefault();
});
<form>
  <label for="input">名前:</label>
  <input type="text" id="input" autofocus>
</form>

input要素のfocusイベントにイベントリスナーを設定し、preventDefault()でデフォルトの動作をキャンセルしています。

これにより、フォーカス時のオートスクロールが抑制されます。

実行結果として、ページ読み込み時にinput要素に自動フォーカスが当たりますが、preventDefault()によってオートスクロールが防止され、ページの位置は変わりません。

まとめ

JavaScriptやjQuery、CSSを使ったスクロールの無効化方法について、実践的なテクニックを数多く紹介してきました。

状況に応じて適切な方法を選び、ユーザー体験を向上させるために活用することが大切です。

スクロール無効化はあくまでも手段であり、むやみに使えばかえって逆効果になることも。

常にユーザーの視点に立ち、本当に必要な場面で適切に활用しましょう。

サンプルコードを参考に、ぜひ自分でもチャレンジしてみてください。

そして、こうした経験の積み重ねがあなたのスキルアップにつながることを願って、締めくくらせていただきます。