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変数は、モーダルのコンテンツ部分ではなく、モーダルを開いた時の背景等を含むモーダル全体の要素を取得しています。

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

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

次に、「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関数と紐付けます。

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

modalはモーダル全体を構成する要素であり、コンテンツ自体は別の要素になるため、コンテンツ自体をクリックしても閉じることができません。
気になる方は、console.log(e.target)で確認してみると、クリックした箇所の要素が取得できるため確認してみてください。

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

まとめ

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

考えられるユーザーのアクションを整理し、イベントを使ってどのように制御していくか考えることが大切です。
JavaScriptの基本の理解を深めながら、ぜひアレンジしてみてください。

モーダルウィンドウの関連記事

DOM
イベントハンドラとイベントリスナー
関数と宣言