JavaScriptには既存の機能として、「alert」「prompt」「confirm」のポップアップウィンドウが用意されています。ユーザーに確認して欲しい内容をダイアログ形式で表示させることができ、当ブログでも活用方法を紹介してきました。

今回は、もう少し実用的なモーダルウィンドウの作り方を解説していきます。

モーダルウィンドウは、元々のウィンドウの上から新たに表示されたウィンドウのことで、指定された操作が完了されるか、キャンセルされるまでは、他のウィンドウに移ることができません。

モーダルウィンドウが使われる場面としては、ページにアクセスしたときに広告が表示されるパターンや、ボタンをクリックすると何かしらの案内が表示されるパターンなどです。

デモ

今回は、ボタンをクリックするとモーダルが開き、バツ印かモーダルコンテンツ外のどこかをクリックするとモーダルが閉じるように実装します。

HTML・CSSの準備

まずはHTMLとCSSを用意します。

HTML

<!DOCTYPE html>
<html labg="en">
<head>
<meta chrset="utf-8" />
<title>Modal App Challenge</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
  <button id="modalOpen" class="button">Click Me</button>
  <div id="easyModal" class="modal">
    <div class="modal-content">
      <div class="modal-header">
        <h1>Great job 🎉</h1>
        <span class="modalClose">×</span>
      </div>
      <div class="modal-body">
        <p>You've just displayed this awesome Modal Window!</p>
        <p>Let's enjoy learning JavaScript ☺️</p>
      </div>
    </div>
  </div>
  <script src="main.js"></script>
</body>
</html>

<span>タグで囲っている乗算の「×」の記号は、HTMLで良く使われる特殊文字「&times;」を記述すると生成できます。

CSS

body {
  font-family: serif;
  font-size: 16px;
  line-height: 1.6;
  color: #fff;
}

.button {
  background: lightblue;
  color: #fff;
  padding: 0 2em;
  border: 0;
  width: 500px;
  height: 100px;
  font-size: 45px;
  border-radius: 5px;
  font-weight: 900;
  position: relative;
  left: 400px;
  top: 260px;
  font-family: serif;
}

.button:hover {
  background: lightcoral;
  cursor: pointer;
}

.modal {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  overflow: auto;
  background-color: rgba(0,0,0,0.5);
}

.modal-content {
  background-color: #f4f4f4;
  margin: 20% auto;
  width: 50%;
  box-shadow: 0 5px 8px 0 rgba(0,0,0,0.2),0 7px 20px 0 rgba(0,0,0,0.17);
  animation-name: modalopen;
  animation-duration: 1s;
}

@keyframes modalopen {
  from {opacity: 0}
  to {opacity: 1}
}

.modal-header h1 {
  margin: 1rem 0;
}

.modal-header {
  background: lightblue;
  padding: 3px 15px;
  display: flex;
  justify-content: space-between;
}

.modalClose {
  font-size: 2rem;
}

.modalClose:hover {
  cursor: pointer;
}

.modal-body {
  padding: 10px 20px;
  color: black;
}

ここでは、よりリアルなモーダルウィンドウの再現するため記述が長めですが、好みのスタイルにカスタマイズしてみてください。

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

HTMLとCSSの準備ができたら、JavaScriptで実装していきます。

全体のコード

const buttonOpen = document.getElementById('modalOpen');
const modal = document.getElementById('easyModal');
const buttonClose = document.getElementsByClassName('modalClose')[0];

//ボタンがクリックされた時
buttonOpen.addEventListener('click', modalOpen);
function modalOpen() {
  modal.style.display = 'block';
};

//バツ印がクリックされた時
buttonClose.addEventListener('click', modalClose);
function modalClose() {
  modal.style.display = 'none';
};

//モーダルコンテンツ以外がクリックされた時
addEventListener('click', outsideClose);
function outsideClose(e) {
  if (e.target == modal) {
  modal.style.display = 'none';
  };
};

今回のモーダルウィンドウを作るうえで、3つの関数を用意します。
・ボタンをクリックしてモーダルを開くための「modalOpen」
・バツ印をクリックしてモーダルを閉じるための「modalClose」
・モーダルコンテンツ以外をクリックしてモーダルを閉じるための「outsideClose」

それでは上から順番にコードを見ていきましょう。

要素を取得する

まずは、必要な要素を取得します。

const buttonOpen = document.getElementById('modalOpen');
const modal = document.getElementById('easyModal');
const buttonClose = document.getElementsByClassName('modalClose')[0];

「getElementById」や「getElementsByClassName」を使って、ボタン・モーダル全体・バツ印の要素を取得します。
modalは、HTMLを確認しても分かる通り、モーダルのコンテンツ部分ではなく、モーダルを開いた時の背景等を含むモーダル全体の要素を取得しています。

これでクリックイベントを発動するための準備が整いました。

ボタンがクリックされた時の機能を作る

つぎに、「Click Me」というボタンがクリックされた時の機能を作ります。

buttonOpen.addEventListener('click', modalOpen);
function modalOpen() {
  modal.style.display = 'block';
};

先ほど取得したボタンの要素に「addEventListner」でクリックイベントを付与し、modalOpen関数と紐付けます。

modalOpen関数の「modal.style.display = ‘block’」は、モーダルの要素を表示する役割があります。
これにより、ボタンがクリックされたら、モーダルが表示されるようになりました。

バツ印がクリックされた時の機能を作る

モーダルが開かれた状態で、バツ印がクリックされた時の機能を作ります。

buttonClose.addEventListener('click', modalClose);
function modalClose() {
  modal.style.display = 'none';
};

クリックイベントを付与するところまでは、モーダルを開く手順と同じです。

異なる点は、モーダルを閉じるために「modal.style.display = ‘none’」と記述します。
これにより、バツ印がクリックされたらモーダルが閉じるようになりました。

「style.display = ‘block’」と「style.display = ‘none’」は、要素の表示と非表示を切り替えるために良く使われています。

モーダルコンテンツ以外がクリックされた時の機能を作る

バツ印をクリックするだけでもモーダルを閉じることができますが、モーダルコンテンツ以外のどこかをクリックした際にもモーダルを閉じることができると便利です。
さいごにそのための機能を作ってみましょう。

addEventListener('click', outsideClose);
function outsideClose(e) {
  if (e.target == modal) {
    modal.style.display = 'none';
  };
};

まずは、クリックイベントを用意し、outsideClose関数と紐付けます。

outsideClose関数のif文に、「e.target」と記述することで、イベントが発生した要素を取得することができます。
つまり、クリックした要素が「modal」だった場合に、モーダルを閉じることができます。

少しややこしいですが、「modal」は、モーダル全体を構成する要素であり、コンテンツ自体は別の要素になるため、コンテンツ自体をクリックしても閉じることができません。

「console.log(e.target);」で確認してみると、クリックした箇所の要素が取得できるため、試してみてください。

以上ですべての実装が完成です。

まとめ

今回はWebサイトやWebアプリなどで良く見かけるモーダルウィンドウを実装していきました。
JavaScriptだけでも意外とかんたんに作ることができると感じたのではないでしょうか。

考えられるユーザーのアクションを整理し、イベントを使ってどのように制御していくか考えることが大切です。

JavaScriptの基本の理解を深めながら、ぜひアレンジしてみてください。

JavaScriptの基本をおさらい