JavaScriptでモーダルウィンドウ実装の仕方

#モーダルウィンドウをjQueryを使わず、JavaScriptのみで実装

覚えたものを備忘録を兼ねてまとめました。

今回実装するのは簡単に説明すると、『詳細をみる』ボタンをクリックすると、デフォルトでつけているhiddenクラスが外されてモーダルとマスクが出現し、『閉じる』ボタンまたは、周りのマスクをクリックすれば、hiddenクラスがついてモーダルが閉じる仕様となっています。



早速雛形のファイルを作っていきます。

##ソース
###HTML



```html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>モーダル</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div id="open">
    詳細をみる
  </div>
  <div id="mask"></div>
  <section id="modal">
    <p>これは簡単なモーダルウィンドウです。</p>
    <div id="close">
      閉じる
    </div>
  </section>
  <script src="script.js"></script>
</body>

</html>


```
JavaScriptでhtml要素を取得するため、idをふっています。

openはモーダル表示、maskはモーダル周りの黒っぽい背景、modalはモーダル、closeは閉じるボタンです。

###CSS



```css:style.css
body {
    font-size: 16px;
  }
  
  #open,
  #close {
    cursor: pointer;
    width: 200px;
    border: 1px solid #ccc;
    border-radius: 4px;
    text-align: center;
    padding: 12px;
    margin: 16px auto 0;
    background: #4caf50;
    color: white;
  }
```

これで一度展開してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577854/d3d8cb51-ab64-a3d6-d8fc-f678725d69c0.png)


このようになればひとまず大丈夫です。

次にmaskとmodalのcss作っていきます。

###マスクとモーダルのCSS



```css:style.css
#mask {
  background: rgba(0, 0, 0, 0.4);
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  z-index: 1;
}

#modal {
  background: #fff;
  color: #555;
  width: 300px;
  padding: 40px;
  border-radius: 4px;
  position: absolute;
  top: 40px;
  left: 0;
  right: 0;
  margin: 0 auto;
  z-index: 2;
}

#modal p {
  margin: 0 0 20px;
}
```

maskはposition: fixed;とrgbaで画面全体を黒っぽくしています。
modalと#maskにz-indexを設定していますが、#maskは#modalより下に来ないと、#modalまで覆いかぶさって黒くなってしまうので、#modal＞#maskに設定しています。

この時点で下の画面のようになるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577854/c1dc8279-b48e-1036-3398-ce3b30d82884.png)

マスクとモーダルは標準時には隠しておきたいので、cssを用いて見えない状態にしておきます。


###display: none;とtransform: translateで隠しておく。


```html:index.html
<div id="mask" class="hidden"></div>
  <section id="modal" class="hidden">
```

```css:style.css
#mask.hidden {
  display: none;
}

#modal.hidden {
  transform: translate(0, -500px);
}
```
htmlで”#maskと#modalにhiddenクラスを命名し、cssで隠します。
maskはdisplay: none;で普通に非表示にしていますが、今回モーダルは上から表示させたいので、
modalはtransform: translate(0,500px);で、500px上に隠しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577854/052c57d0-5841-d2db-b254-31e577599e3d.png)

消えていたら、JavaScriptに入ります。

##JavaScriptでマスクとモーダルを操作する

今回は、『openをクリックすると、#modalと#maskのhiddenクラスが取り除かれて表示する』という設計なので、openにクリックイベントをつけていきます。

```js:script.js
'use strict';
{
  const open = document.getElementById('open');
  const close = document.getElementById('close');
  const modal = document.getElementById('modal');
  const mask = document.getElementById('mask');

  open.addEventListener('click', function () {
    modal.classList.remove('hidden');
    mask.classList.remove('hidden');
  });
}
```

これで、”詳細をみる”をクリックすることで、モーダルとマスクのhiddenクラスが外されて、表示されるのが確認できるはずです。
しかし、再び非表示にすることはできないので、今度はhiddenクラスを再クリックで付与できるようにします。
また、マスク部分を押しても非表示にできた方がユーザビリティ的にも自然なので、maskにもクリックイベントを適用します。

```js:script.js
'use strict';
{
  const open = document.getElementById('open');
  const close = document.getElementById('close');
  const modal = document.getElementById('modal');
  const mask = document.getElementById('mask');

  open.addEventListener('click', function () {
    modal.classList.remove('hidden');
    mask.classList.remove('hidden');
  });
  close.addEventListener('click', function () {
    modal.classList.add('hidden');
    mask.classList.add('hidden');
  });
  mask.addEventListener('click', function () {
    modal.classList.add('hidden');
    mask.classList.add('hidden');
  });
}
```


##最後にアニメーションを

モーダルを上からにゅっと表示させるため、transitionを追加してやります。すぐに出来ます。


```css:style.css
#modal {
  background: #fff;
  color: #555;
  width: 300px;
  padding: 40px;
  border-radius: 4px;
  position: absolute;
  top: 40px;
  left: 0;
  right: 0;
  margin: 0 auto;
  z-index: 2;
  transition: 0.4s;
}
```

modalにtransitionを追加するだけです。
これで完成です。





ご閲覧ありがとうございます。