この記事では「JavaScriptでモーダルウィンドウを表示させる方法」について解説します。
モーダルウィンドウはWebサイトで出てくる頻出の実装の一つなので、実装方法を覚えておきましょう。
- JavaScriptでモーダルウィンドウを表示させる方法について分かる
- モーダルウィンドウの実装がコピペでできる様になる
モーダルウィンドウの実装方法
コードは以下になります
See the Pen モーダル実装 by 山中滉大 (@tips-web) on CodePen.
<div class="l-modal" id="js-modal">
<div class="p-modal">
<div class="p-modal__contents">
<div class="p-modalBox__button">
<button class="c-closeButton" type="button">
<span></span>
<span></span>
</button>
</div>
<div class="p-modal__block">
モーダルのコンテンツ
</div>
</div>
</div>
</div>
<section class="p-section">
セクション
</section>
<section class="p-section">
セクション
</section>
<section class="p-section">
セクション
</section>
<section class="p-section">
セクション
</section>
<div class="p-float">
<button class="c-floatButton" type="button">
<p class="c-floatButton__text">モーダル<br>ボタン</p>
</button>
</div>
.c-closeButton {
background: #000;
border-radius: 50%;
z-index: 10;
position: relative;
width: 32px;
height: 32px;
border: 1px solid #fff;
cursor: pointer;
}
.c-closeButton span {
display: inline-block;
position: absolute;
top: 50%;
left: 0;
width: 32px;
height: 2px;
background: #fff;
}
.c-closeButton span:nth-child(1) {
transform: rotate(45deg);
}
.c-closeButton span:nth-child(2) {
transform: rotate(-45deg);
}
.c-floatButton {
display: block;
position: relative;
cursor: pointer;
background-color: orange;
padding: 40px;
}
.c-floatButton__text {
color: #000;
font-size: 14px;
font-weight: 700;
line-height: 1.5;
text-align: center;
}
.p-section {
width: 100%;
height: 200px;
background-color: lightcyan;
}
.p-section:nth-child(2n) {
background-color: lightgray;
}
.l-modal {
position: fixed;
top: 0;
left: 0;
z-index: 999;
height: 100vh;
width: 100%;
display: none;
}
.l-modal.is-show {
display: block;
}
.p-modal {
padding-top: 100px;
padding-bottom: 100px;
position: relative;
height: inherit;
padding-left: 28px;
padding-right: 28px;
display: flex;
align-items: center;
justify-content: center;
}
.p-modal::before {
background-color: #000;
opacity: .5;
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.p-modal__contents {
position: relative;
width: 100%;
max-width: 700px;
}
.p-modal__block {
position: relative;
background-color: lightblue;
width: inherit;
height: 400px;
z-index: 1;
}
.p-modalBox__button {
position: absolute;
top: -16px;
right: -16px;
}
.p-modalBox__button {
text-align: center;
}
.p-float {
z-index: 100;
position: fixed;
right: 34px;
bottom: 66px;
}
document.addEventListener('DOMContentLoaded', function() {
const modal = document.querySelector('#js-modal');
const floatModal = document.querySelector('.c-floatButton');
const modalClose = document.querySelector('.c-closeButton');
const body = document.querySelector('body');
if (!modal) {
return false;
}
modalClose.addEventListener('click', function() {
modal.classList.remove('is-show');
resetStyles();
});
modal.addEventListener('click', function() {
modal.classList.remove('is-show');
resetStyles();
});
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
let pos;
floatModal.addEventListener('click', function() {
modal.classList.add('is-show');
pos = window.pageYOffset || document.documentElement.scrollTop;
body.style.overflow = 'hidden';
body.style.position = 'fixed';
body.style.width = `calc(100% - ${scrollbarWidth}px)`;
body.style.top = -pos + 'px';
body.style.marginRight = `${scrollbarWidth}px`;
});
function resetStyles() {
body.style.overflow = 'initial';
body.style.position = 'static';
body.style.width = 'initial';
body.style.marginRight = '0';
window.scrollTo(0, pos);
}
});
〇 モーダル非表示画面
〇 モーダル表示画面
右下のフロートボタンをクリックすると、画面中央にモーダル画面が開きます。モーダルコンテンツの右上にある×ボタン、もしくは背景をクリックするとモーダルが閉じます。
また、モーダルが開いている間、モーダルの背景が上下にスクロールできないように画面を固定させています。
モーダルの作成イメージは以下になります。
よりコーディングの速度を効率良く上げていきたい方はスニペットを活用するのがいいです。
コードを保管してコピペで対応できる様にしておきましょう。
時短コーディングへの第一歩はこちらから▶︎
HTMLの解説
モーダル部分のHTMLは以下になります。
<div class="l-modal" id="js-modal">
<div class="p-modal">
<div class="p-modal__contents">
<div class="p-modalBox__button">
<button class="c-closeButton" type="button">
<span></span>
<span></span>
</button>
</div>
<div class="p-modal__block">
モーダルのコンテンツ
</div>
</div>
</div>
</div>
モーダル表示時の黒背景は後述するCSSの疑似要素で作成しています。
モーダルを表示した後、モーダルを非表示にするためのボタンもbuttonタグで作成します。
モーダルには、JavaScriptで制御するためにId属性を付与しておきます。
CSSの解説
モーダル表示時の黒背景は以下の疑似要素で作成しています。
.p-modal {
padding-top: 100px;
padding-bottom: 100px;
position: relative;
height: inherit;
padding-left: 28px;
padding-right: 28px;
display: flex;
align-items: center;
justify-content: center;
}
.p-modal::before {
background-color: #000;
opacity: .5;
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
モーダルは初期時様態は非表示、is-showクラスが付与されたとき表示するので、以下のように記述します。
.l-modal {
position: fixed;
top: 0;
left: 0;
z-index: 999;
height: 100vh;
width: 100%;
/* 初期状態は非表示 */
display: none;
}
/* is-showクラス付与でモーダル表示 */
.l-modal.is-show {
display: block;
}
JavaScriptの解説
まず以下のように処理に必要な要素を以下のように取得し、変数に格納します。
const modal = document.querySelector('#js-modal'); // モーダル要素を取得
const floatModal = document.querySelector('.c-floatButton'); // フロートモーダル要素を取得
const modalClose = document.querySelector('.c-closeButton'); // モーダルの閉じるボタン要素を取得
const body = document.querySelector('body'); // body要素を取得
モーダルの閉じるボタン(c-closeButton)をクリックしたら、モーダルに付与されていたis-showクラスを削除する処理を作成します。
modalClose.addEventListener('click', function() {
modal.classList.remove('is-show');
});
また、モーダルを表示した後、モーダル自身や背景をクリックするとモーダルが閉じるように、上記と同様の処理を作成します。
modal.addEventListener('click', function() {
modal.classList.remove('is-show');
});
右下のフロートボタンをクリックしてモーダルが開く処理は以下になります。
floatModal.addEventListener('click', function() {
modal.classList.add('is-show');
});
モーダルが開いている間、画面をスクロールできないように画面固定にする処理は以下になります。
背景固定時の画面カクつきを抑えるための処理も行います。
以下はスクロールバーの幅を計算したものを、変数に格納しています。
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; // スクロールバーの幅を計算
let pos;
モーダルを開く処理に以下の記述を追記します。
floatModal.addEventListener('click', function() {
modal.classList.add('is-show'); // モーダルの表示クラスを追加
// 以下追記
pos = window.pageYOffset || document.documentElement.scrollTop; // スクロール位置を保存
body.style.overflow = 'hidden';
body.style.position = 'fixed'; // body要素を固定位置に設定
body.style.width = `calc(100% - ${scrollbarWidth}px)`; // スクロールバーの幅を考慮した幅に設定
body.style.top = -pos + 'px'; // スクロール位置を補正
body.style.marginRight = `${scrollbarWidth}px`; // スクロールバーの幅分のマージンを設定
});
上記の記述をすると、モーダル表示時bodyタグにスタイルが適用されます。検証ツールを開くと、bodyタグにスタイルが適用されているのが分かります。
最後に、モーダルを閉じた際に画面固定処理を初期化する処理を作成します。
function resetStyles() {
body.style.overflow = 'initial';
body.style.position = 'static';
body.style.width = 'initial';
body.style.marginRight = '0';
window.scrollTo(0, pos);
}
作成した関数は、以下のようにモーダルを閉じる処理にそれぞれ追記していきます。
modalClose.addEventListener('click', function () {
modal.classList.remove('is-show');
// 初期化処理を追記
resetStyles(); // スタイルをリセット
});
modal.addEventListener('click', function () {
modal.classList.remove('is-show');
// 初期化処理を追記
resetStyles(); // スタイルをリセット
});
まとめ
JavaScriptでモーダルウィンドウを表示させる方法について解説しました。
一つ一つ何の処理が必要なのか考えながら実装していきましょう。