• SEARCH

SEARCH

チェックボックスにチェックをつけたうえで検索すると、
該当のカテゴリ記事に絞り込むことができます。

ホームページ制作のご依頼・ご相談はCOLERSへ

SNIPPETのロゴ

JavaScriptとCSSでライブラリを使わずにモーダルウィンドウを追加する

JavaScriptでモーダルウィンドウを実装する

簡易的なモーダルウィンドウであればライブラリを使わずに
素のJavaScript(Vanilla JS)CSSのみで追加することが可能です。

クラスの追加のみをJavaScriptで行い、
実際のアニメーションはCSSで実装する方法でご紹介いたします。

実際のコード

<div class="modal-cover" id="js-modal-cover"></div>
<div class="block">
  <h2 class="block__ttl">タイトルですよ</h2>
  <p class="block__desc">
    説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 
  </p>
  <button type class="block__btn" id="js-modal-btn">モーダルを開く</button>
</div>

<div class="modal-block" id="js-modal">
  <h2 class="modal-block__ttl">モーダルウィンドウだよ</h2>
  <p class="modal-block__desc">
    説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 説明です 
  </p>
  <button type class="block__btn" id="js-modal-close">モーダルを閉じる</button>
</div>
.modal-cover {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  background: rgba(0,0,0,.8);
  z-index: 2;
  display: none;
  transition: all .3s ease 0s;
  &.is-active {
    display: block;
  }
}

.modal-block {
  position: fixed;
  right: 0;
  left: 0;
  z-index: 3;
  background: #fff;
  width: 600px;
  margin: 0 auto;
  padding: 24px;
  transition: all .3s ease 0s;
  &.is-active {
    bottom: 32px !important;
  }
}

.block__btn {
  cursor: pointer;
}

なお、CSSの場合は以下の記述となります。

.modal-cover {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  background: rgba(0,0,0,.8);
  z-index: 2;
  display: none;
  transition: all .3s ease 0s;
}

.modal-cover.is-active {
  display: block;
}

.modal-block {
  position: fixed;
  right: 0;
  left: 0;
  z-index: 3;
  background: #fff;
  width: 600px;
  margin: 0 auto;
  padding: 24px;
  transition: all .3s ease 0s;
}

.modal-block.is-active {
  bottom: 32px !important;
}

.block__btn {
  cursor: pointer;
}
const modal = document.querySelector("#js-modal");
const modalBtn = document.querySelector("#js-modal-btn");
const modalClose = document.querySelector("#js-modal-close");
const modalCover = document.querySelector("#js-modal-cover");

const modalHeight = modal.clientHeight;
modal.style.bottom = `-${modalHeight}px`;

const closeModal = () => {
  modal.style.bottom = `-${modalHeight}px`;
  modalCover.classList.remove("is-active");
  modal.classList.remove("is-active");
};

modalBtn.addEventListener("click", () => {
  modalCover.classList.add("is-active");
  modal.classList.add("is-active");
});

modalClose.addEventListener("click", () => {
  closeModal();
});

modalCover.addEventListener("click", () => {
  closeModal();
});

実装の結果

javascript-modal-window

実装についての補足と解説

それぞれのコードのポイントについて解説します。

CSS

ページ全体を覆う要素、下から表示するモーダルウィンドウ、
それぞれに対してis-activeクラスの有無によるスタイル変化がポイントなります。

modal-cover

この要素はdisplay:noneで非表示にしていますが、
モーダルウィンドウを起動した場合のみdisplay:blockで表示され、
既存のコンテンツを半透明の黒い背景で覆います。

役割としてはモーダルウィンドウがアクティブになっていることで、
既存の要素をクリックできなくすることとクリックできないんだと視覚的に
認識してもらうことです。

.modal-cover {
  position: fixed; // ウィンドウに対して固定
  top: 0; // 一番上に固定
  right: 0;// 一番左にも固定
  left: 0;// 一番右にも固定
  bottom: 0;// 一番下にも固定。つまり画面全体に固定
  background: rgba(0,0,0,.8);// 背景の色は80%透明の黒
  z-index: 2;// 重なり順が上になるように指定
  display: none;// 普段は非表示
  transition: all .3s ease 0s;// 変化があったら0.3秒でアニメーション
}

.modal-cover.is-active {
  display: block;// is-activeクラスが付与されたら表示する
}

modal-block

実際のモーダルウィンドウの要素になります。
画面を開いた状態では非表示ですが、CSS側では非表示の指定はせずに、
ウィンドウとしての基本スタイルとis-activeクラスを付与された場合の挙動のみ指定しています。

指定の中で!importantを付与している部分は他のCSSとルールが重複した場合も強制させることができます。
※多用するとルールの崩壊を招くので意図する場合のみ利用するのがベスト。

.modal-block {
  position: fixed;// ウィンドウに対して固定
  right: 0;// 一番左に固定
  left: 0;// 一番右に固定
  z-index: 3;// 重なり順がmodal-coverより上になるように数字を3にする
  background: #fff;// 背景は白
  width: 600px;// ウィンドウの横幅は600px
  margin: 0 auto;// 画面の中央寄せ
  padding: 24px;// ウィンドウ内の余白を上下左右24px
  transition: all .3s ease 0s;// 変化があったら0.3秒でアニメーション
}

.modal-block.is-active {
  bottom: 32px !important;// is-activeクラスが付与されたらウィンドウの下から考えて32pxの位置に固定。
}

JavaScript

HTMLの要素に対して操作を行っていくため、
まずはquerySelectorを利用して取得を行っています。

シャープ(#)はIDを指しているため、id=”js-modal”という要素であれば、
#js-modalと指定することで取得することが可能です。
※クラスの場合はドット(.)を利用します。

const modal = document.querySelector("#js-modal");
const modalBtn = document.querySelector("#js-modal-btn");
const modalClose = document.querySelector("#js-modal-close");
const modalCover = document.querySelector("#js-modal-cover");

モーダルウィンドウはページを開いた段階では非表示の想定のため、
以下のように非表示の処理を施しています。

CSSでの指定でも良いのですが高さが変動するケースをふまえて、
実際のモーダルウィンドウのコンテンツ量が変わっても対応できるようにしました。

const modalHeight = modal.clientHeight;// モーダルウィンドウの高さを取得
modal.style.bottom = `-${modalHeight}px`;// 取得した高さ分ウィンドウの下に移動させることで結果的にウィンドウ外に移動しており非表示になる

ボタンのクリックで表示したり非表示にしたりを切り替えますが、
非表示処理はボタンおよびmodal-coverエリアをクリックした場合も同様のため、
関数にして使い回しができるようにしました。

const closeModal = () => {
  modal.style.bottom = `-${modalHeight}px`;
  modalCover.classList.remove("is-active");
  modal.classList.remove("is-active");
};
// これは関数で処理をまとめているだけのため、実際にcloseModal()を呼び出すことではじめて実行される

最後にそれぞれのボタンやmodal-coverエリアにイベントを設定しています。
基本的にはis-activeの付け替えだけがメインの役割のため、
CSSにアニメーションのほとんどを担当させています。

modalBtn.addEventListener("click", () => {
  modalCover.classList.add("is-active");
  modal.classList.add("is-active");
});

modalClose.addEventListener("click", () => {
  closeModal();
});

modalCover.addEventListener("click", () => {
  closeModal();
});

最後に

あえてライブラリを使わないという選択肢での実装をご紹介しました。
やりたいこととそれに対する工数のバランスを考えたときに
自作するという方法もありだと思います。

ただ既存のライブラリは優秀なプログラマーたちの知見が詰められており
非常に高機能かつ安定性の高いものが多いです。

あえて自作することにするとデメリットが多い場面もありますので、
自分のやりたいことをふまえて、最適な選択肢を選んでいただければ幸いです。

AUTHOR

Yasuhiro Yamamoto

Yasuhiro Yamamoto

福岡市在住のフリーランス。
WEBデザイナー、フロントエンドエンジニア、アプリーケーションエンジニア。
デザイン・ディレクション・実装など、企画〜完成まで一貫して承っている。

RECOMMEND