JavaScript

【サンプルあり】ネイティブJavaScriptでスクロールのできる簡単なモーダルウィンドウを作る

JavaScriptで簡単なモーダルウィンドウを作成しました。
以下サンプルです。

See the Pen Modal Window by POSIPAN (@posipan) on CodePen.

仕様

  • 「モーダルを開く」をクリックすると、モーダルウィンドウが表示させる
    (アニメーションなし)
  • モーダルウィンドウ内ではコンテンツがスクロールできる
  • 右上の閉じるボタン、またはオーバーレイ背景をクリックでモーダルウィンドウを閉じる

作り方

HTMLで雛形を作る

今回モーダルウィンドウ内のHTMLはJavaScriptで動的に生成しているのですが、
事前準備としてまずはHTMLで組んでいきます。

<a href="https://yahoo.co.jp" target="_blank" id="modal-btn">モーダルを開く</a>
<div id="modal">
  <div id="modal-inner">
    <div id="modal-content">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sed ornare augue. Sed sit amet malesuada nisl. Pellentesque egestas tempor ligula, id dictum dolor egestas at. Nulla ornare vestibulum ex et egestas. Vivamus at luctus tortor, ac auctor ipsum. Vivamus vestibulum volutpat felis, id malesuada dolor. Mauris elit nulla, consectetur id consectetur at, cursus in elit. Proin lectus lacus, posuere in nisi eu, consectetur sagittis justo. Aliquam quis venenatis lorem, sit amet consectetur magna. Aliquam vitae velit vel est volutpat lobortis. Suspendisse potenti. Ut a sagittis enim. Fusce et purus tempus, auctor lectus vel, finibus velit.Fusce ut nulla convallis, vestibulum risus eget, consequat nulla. Suspendisse potenti. Suspendisse potenti. Cras at eros posuere, sagittis quam vitae, laoreet tellus. Duis semper iaculis ligula quis sollicitudin. Etiam condimentum cursus erat at malesuada. Proin convallis, ante id cursus elementum, nisl lectus ullamcorper erat, a posuere magna sem non turpis. Nulla non ante imperdiet, suscipit nunc ac, commodo mauris.
    </div>
  </div>
  <div id="close"></div>
</div>
<div id="overlay"></div>

コンテンツスクロールができるように#modal-innerというdivタグで#modal-contentを囲っています。

また、オーバーレイ背景はモーダルウィンドウの要素と分離しています。

CSSで整える

SCSSを使用して作成しています。

コンテンツスクロールは以下のように実装しています。

  • モーダルウィンドウ内のテキストが長く、要素からはみ出てしまうので
    #modaloverflow: hidden;を追加
  • 子要素である#modal-innerに対して、
    高さ(親要素の高さ – 親要素のpadding)とoverflow: scroll;を追加

また、モーダルウィンドウは上下中央に配置し、閉じるボタンやオーバーレイ背景にはクリックできる要素であることがわかるようにcursor: pointer;を追加します。

#modal {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  transform: translate(-50%, -50%);
  background: #fff;
  padding: 30px 40px;
  width: 300px;
  height: 200px;
  overflow: hidden;
  #modal-inner {
    height: 140px;
    overflow: scroll;
  }
  #close {
    position: absolute;
    top: 0;
    right: 0;
    width: 40px;
    height: 40px;
    cursor: pointer;
    &:before,
    &:after {
      display: block;
      content: "";
      background: #333;
      width: 30px;
      height: 2px;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%) rotate(45deg);
    }
    &:after {
      transform: translate(-50%, -50%) rotate(-45deg);
    }
  }
}

#overlay {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.5);
  cursor: pointer;
}

JavaScriptで要素と動きを作る

モーダルウィンドウの要素生成や、生成要素へのクリックイベントの追加は関数化(modalFunc())して、コードの見通しを良くしています。

続いてコード上部にあるmodalBtnにクリックイベントを追加して、modalFunc()を呼び出します。

modalBtnにはa要素が代入されているので、デフォルトの挙動であるリンク機能をOFFにするためにe.preventDefault()を追加しましょう。

const modalBtn = document.getElementById('modal-btn');
modalBtn.addEventListener('click', function(e) {
  e.preventDefault();
  modalFunc();
});

function modalFunc() {
  // #modal
  const modal = document.createElement('div');
  modal.id = 'modal';
  
  // #modal-inner
  const modalInner = document.createElement('div');
  modalInner.id = 'modal-inner';
  
  // #modal-content
  const modalContent = document.createElement('div');
  modalContent.id = 'modal-content';
  modalContent.textContent = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sed ornare augue. Sed sit amet malesuada nisl. Pellentesque egestas tempor ligula, id dictum dolor egestas at. Nulla ornare vestibulum ex et egestas. Vivamus at luctus tortor, ac auctor ipsum. Vivamus vestibulum volutpat felis, id malesuada dolor. Mauris elit nulla, consectetur id consectetur at, cursus in elit. Proin lectus lacus, posuere in nisi eu, consectetur sagittis justo. Aliquam quis venenatis lorem, sit amet consectetur magna. Aliquam vitae velit vel est volutpat lobortis. Suspendisse potenti. Ut a sagittis enim. Fusce et purus tempus, auctor lectus vel, finibus velit.Fusce ut nulla convallis, vestibulum risus eget, consequat nulla. Suspendisse potenti. Suspendisse potenti. Cras at eros posuere, sagittis quam vitae, laoreet tellus. Duis semper iaculis ligula quis sollicitudin. Etiam condimentum cursus erat at malesuada. Proin convallis, ante id cursus elementum, nisl lectus ullamcorper erat, a posuere magna sem non turpis. Nulla non ante imperdiet, suscipit nunc ac, commodo mauris.';
  
  // #close
  const closeBtn = document.createElement('div');
  closeBtn.id = 'close';
  
  // オーバーレイ
  const overlay = document.createElement('div');
  overlay.id = 'overlay';
  
  // appendChildで親要素に子要素を追加
  modalInner.appendChild(modalContent);
  modal.appendChild(modalInner);
  modal.appendChild(closeBtn);

  document.body.appendChild(modal);
  document.body.appendChild(overlay);
  
  overlay.addEventListener('click', function() {
    modal.remove();
    this.remove();
  });
  closeBtn.addEventListener('click', function() {
    modal.remove();
    overlay.remove();
  });
}

完成です!

おわりに

あえてHTML要素をJavaScriptで作る簡単なモーダルウィンドウを作成してみましたが、コードが長いですね。。。

また、モーダル内のテキストをJavaScriptで作ってしまっているのでSEO的にもよろしくないでしょう。

モーダルウィンドウの要素を、JavaScriptで制御する方(classの追加・削除で表示・非表示の切り替え)が楽ですね😜

ではまた👍