これでモーダルウィンドウの背景スクロールを固定できます!

目次

「モーダルを開いたときに背景を固定して!」とお願いされたら

対応する機会が多い仕様ではないですが、忘れたころにやってくるこのお願い。

「昔やった気がするけど、ちょっとややこしかったような…」

と不安になります。
これ、CSSだけで対応しようとすると失敗するんですよね。
私も昔失敗しました…

急な依頼でも慌てることがないように、ポイントを押さえて見ていきましょう。

【基本コード】モーダルの背景を固定しよう

JavaScript

//変数の設定
var $body = $('body');

//スクロール量を保存
var scrollTop;

//スクロールを固定
function bodyFixedOn() {
  scrollTop = $(window).scrollTop();
  
  $body.css({
    position: 'fixed',
    top: -scrollTop
  });
}

//スクロールの固定を解除
function bodyFixedOff() {
  $body.css({
    position: '',
    top: ''
  });
  
  $(window).scrollTop(scrollTop);
}

//モーダルのトリガーをクリックしたとき
$('.modal-trigger').on('click', function() {
  bodyFixedOn();
});

//モーダルの閉じるボタンをクリックしたとき
$('.modal-close').on('click', function() {
  bodyFixedOff();
});

//モーダルのオーバーレイをクリックしたとき
$('.overlay').on('click', function() {
  bodyFixedOff();
});

HTML

<!-- モーダルを開くボタン -->
<a class="modal-trigger" href="#">
  モーダルを開く
</a>

<!-- モーダル本体 -->
<div class="modal-wrap">
    <div class="overlay"></div>
    <div class="modal-inner">
        <div class="img">
            モーダルが開きました。<br>背景も固定されました。
        </div>
        <button class="modal-close">×</button>
    </div>
    <!-- /.modal-inner -->
</div>
<!-- /.modal-wrap -->

SCSS

.modal-wrap{
  position: fixed;
  top: 0;
  left: 0;
  display: block;
  width: 100%;
  height: 100vh;
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s linear, visibility .3s linear;
  z-index: -1;
  
  .overlay{
    position: fixed;
    top: 0;
    left: 0;
    display: block;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, .8);
    cursor: pointer;
  }
  
  .modal-inner{
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    background: rgba(255, 255, 255, .8);
    transform: translate(-50%, -50%);
    
    .modal-close{
      position: absolute;
      cursor: pointer;
    }
  }
  
  &.show{
    opacity: 1;
    visibility: visible;
    z-index: 10000;
  }
}

@media screen and (min-width: 768px) {
  .modal-trigger{
    transition: opacity .3s linear;
  }
  
  .modal-wrap{
    .modal-inner{
      max-width: 960px;
      
      .modal-close{
        top: -48px;
        right: 0;
      }
    }
  }
}

@media screen and (max-width: 767px) {
  .modal-wrap{
    .modal-inner{
      width: 90%;
      
      .modal-close{
        top: -30px;
        right: 0;
      }
    }
  }
}

こんな感じでしょうか。
HTMLやCSSはデザインに合うように調整してください。

【Demo】モーダルの背景を固定しよう

See the Pen bodyFIxed by Yusuke Saio (@saio-th) on CodePen.

【Point】モーダルの背景を固定しよう

  • スクロール量を取得する
  • モーダルを開くときはスクロール量を「CSS」でbody要素に設定する
  • モーダルを閉じるときはスクロール量を「JavaScript」でwindowオブジェクトに設定する

【解説】モーダルの背景を固定しよう

細かくコードを見ていきましょう。

詳細に説明するために一部上記と異なるコードが出てきます。
実際に使用するときは「基本コード」を参考にしてください

スクロール量を取得

スクロールの固定は「スクロール量」を指定したり解除したりすることで実現します。

ということで、まずはスクロール量を取得する必要があります。
スクロール量は$(window).scrollTop()メソッドで取得できます。

「モーダルウィンドウを開く」ボタンをクリックしたときに取得してください。

//例
$('.modal-trigger').on('click', function() {
  scrollTop = $(window).scrollTop();
});

モーダルが開いたらbody要素を固定して、CSSでスクロール量を設定する

次に、スクロールを固定する処理を実装します。
具体的には以下の処理をほどこします。

  • body要素をposition: fixed;で固定する
  • body要素の位置を、スクロール量分上にずらす

こうすることで、
モーダルを開く前後で背景がズレません。

//例
$('.modal-trigger').on('click', function() {
  scrollTop = $(window).scrollTop();
  
  $('body').css({
    position: 'fixed',
    top: -scrollTop
  });
});

topプロパティにスクロール量を指定しないとどうなるでしょうか?
モーダルを開いた瞬間に背景がページの一番上に戻ってしまいます。

忘れずに指定しましょう!

モーダルを閉じたらbody要素の固定を解除して、JavaScriptでwindowオブジェクトにスクロール量を設定する

最後に、「モーダルを閉じるボタン」やオーバーレイをクリックした時に
固定を解除する処理を実装します。

  • body要素に指定したCSSを解除する
  • windowオブジェクトにモーダルオープン前のスクロール量を指定する

これでモーダルを開く前の状態に戻すことができます。

//例
$('.modal-close').on('click', function() {
  $('body').css({
    position: '',
    top: ''
  });
  
  $(window).scrollTop(scrollTop);
});

上記コードの通り、
windowオブジェクトにスクロール量を設定するのにもscrollTop()メソッドを使用します。
scrollTop()メソッドの引数に数値を指定することでスクロール量を指定することができます。

以上で一連の流れが完了です。

【まとめ】モーダルの背景を固定しよう

昔私が失敗したのは、
取得したスクロール量をCSSだけで制御しようとしたことが原因でした。

ポイントはモーダルを閉じたときに
windowオブジェクトに対してスクロール量を設定」
すること!!

以上です。
少しでもお役に立てたら嬉しいです。

参考サイト

■モーダルを開いている時にページがスクロールしてしまうのを防ぐCSSとJavaScriptのテクニック
https://coliss.com/articles/build-websites/operation/javascript/prevent-page-scrolling-when-a-modal-is-open.html

Share

Comments

コメントを残す

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。

CAPTCHA