モーダル内のコンテンツがスクロールするときでも、背景をコンテンツいっぱいにする

こんにちは!のせっちです!

モーダル内のコンテンツがスクロールするときでも背景を画面いっぱいにする方法をご紹介します。

通常の書き方

まずは、通常の書き方を抑えておきます。
基本がわかっていないと、理解できないからです。

See the Pen modal by Yuki Nose (@yukinouz1) on CodePen.

// モーダル展開時の背景部分

.modal__bg{
  background: rgba(#000, 0.8);
  height: 100vh;
  position: absolute;
  width: 100%;
}

モーダル展開時の黒背景部分のみ抜粋です。
height: 100vh;で高さを画面いっぱいにしています。

$(()=> {
  const modal = $(".js-modal");
  const modalOpen = $(".js-modal-open");
  const modalClose = $(".js-modal-close");

  modalOpen.on("click", function() {
    modal.fadeIn();
  });
  modalClose.on("click", function() {
    modal.fadeOut();
  });
});

ボタンクリックでモーダルを展開、閉じるボタンか黒背景をクリックで閉じる、という単純なjQueryを書いています。

()=>アロー関数といい、今回のケースではfunction()と書いているのと同じです。

モーダル内のコンテンツがスクロールする場合

次に、モーダル内のコンテンツがスクロールする場合を見てみます。

See the Pen modal-overflow-y by Yuki Nose (@yukinouz1) on CodePen.

ボタンクリックでモーダルを開くのは同じです。
今回はコンテンツがY方向にoverflowしていて、縦スクロールが発生していますね!
それでも、黒背景はコンテンツの最後まで広がっています。

height: 100vh;だと画面の表示部分しか確保できないので、スクロールしていくと黒背景は途切れるはずです。

どうやってコンテンツ全体を黒背景で覆っているのでしょうか?

解説

簡単に解説します。

まずはCSSです。

.modal__bg{
  background: rgba(#000, 0.8);
  min-height: 100vh;
  position: absolute;
  width: 100%;
}

height: 100vh;ではなく、min-height: 100vh;としました。

height: 100vh;では、表示領域分しか高さが取れないので、スクロールしていくと黒背景は途切れます。
なので高さはjavascriptで計算します。

min-height: 100vh;とした理由は、ワイドスクリーンというか、縦長スクリーン対応です。縦長でスクロールがなくなる可能性があるので、そのときは100vhが適用されるようにしてあげます。

$(() => {
  const modal = $(".js-modal");
  const modalContent = $(".js-modal-content");
  const modalBg = $(".js-modal-bg");
  const modalOpen = $(".js-modal-open");
  const modalClose = $(".js-modal-close");
  const body = $("body");
  
  modalOpen.on("click", function() {
    modal.fadeIn();
    body.css({
      overflow: "hidden",
    });
    let formheight = modalContent.outerHeight();
    modalBg.css({
      height: formheight
    });
  });
  modalClose.on("click", function() {
    modal.fadeOut();
    body.css({
      overflow: "auto",
    });
    modalBg.css({
      height: "auto"
    });
  });
});

こちらは分解して細かく解説します。

// 定義省略
  modalOpen.on("click", function() {
    modal.fadeIn();
    body.css({
      overflow: "hidden",
    });
    formheight = modalContent.outerHeight();
    modalBg.css({
      height: formheight
    });
  });

クリックでモーダルをfadeIn()させるところまでは基本形と同じです。

body.css({overflow: "hidden",});としているのはモーダルオープン時にページ全体がスクロールしないようにするためです。

「モーダル展開時 ページスクロールしない」とかでググると沢山出てくるやり方です。

formheight = modalContent.outerHeight();でコンテンツの高さを取得して、formheightという変数に代入しました。

modalBg.css({height: formheight});で先ほど計算した黒背景部分のcssでheightをformheightにしてあげます。

こうすることで、クリックしたときの高さを黒背景の高さにすることができます。

次は閉じる動作をしたときの処理です。

modalClose.on("click", function() {
    modal.fadeOut();
    body.css({
      overflow: "auto",
    });
    modalBg.css({
      height: "auto"
    });
  });

モーダルを閉じるときは、bodyのoverflowを元に戻す、黒背景の高さもautoに戻す、という処理です。
基本全部元に戻す処理をしてあげているだけです!

最後です。

// 定義省略  
  $(window).on("resize", function() {
    formheight = modalContent.outerHeight();
    modalBg.css({
      height: formheight
    });
  });

$(window).on("resize", function()...でウィンドウのリサイズを検知できます。

スマホサイズ、タブレットサイズ、PCサイズでコンテンツの高さは違いますので、windowのサイズ変更にも対応できるようにしています。

モーダル展開時にもformheightを取得しますが、modalOpen.on("click", function()...なので、クリックしたとき1回だけ取得します。リサイズに対応するには、別で処理を書かないといけません。

お疲れ様でした。

まとめ

・モーダル内のコンテンツがスクロールする場合はjsで高さを計算する。
・ワイドスクリーン(縦長スクリーン)に対応するために、min-height: 100vh;を書いておく。
・widnowサイズの変更にも対応する。

この記事を書いた人

のせっち

福岡県出身。早稲田大学卒。創業100年の鉄鋼商社でバンコク駐在最年少抜擢。毎日擦り切れるまで働かなくても幸せに生きている人々を見てフリーランスになりました。
現在は、主にバンコクでWeb制作、物販を中心に生きています。