モーダルウィンドウ
2022年8月25日
みなさんこんにちは。
ケミストのWeb担当みやのです。
「Web」記事では、これまでに得たWebに関する知識を記録として残していきたいと思います。
今回は、検査値の記事で使った「モーダルウィンドウ」について書きます。
モーダルウィンドウとは
モーダルウィンドウとは、元のウィンドウのさらに前面に表示される小さなウィンドウのことです。
モーダルウィンドウが開いている間は閉じない限り他の操作ができないようになっています。
modalとは「モードを持つ」という意味であり、つまりモーダルウィンドウとは「ユーザーの応答待ちモードになっているウィンドウ」と言えます。
風の流法 !そのふたつの拳の間に生じる真空状態の圧倒的破壊空間はまさに歯車的砂嵐の小宇宙!!
同じく最前面に表示されるものとして「ポップアップ」がありますが、こちらは開いていても他の操作ができるという違いがあります。
実装
Bootstrapにはあらかじめモーダルウィンドウのクラスが用意されているのでそれを使います。
参考:Bootstrap4.2日本語リファレンス|Modal
まずはモーダルウィンドウを作ります。
クラス名はmodal、IDは何でもいいですが仮にModal1としておきます。
ふわっと表示させるために、fadeというクラスも付与します。
<div class="modal fade" id="Modal1" tabindex="-1" role="dialog" aria-labelledby="Modal1Label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="Modal1Label">タイトル</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
テキスト
テキスト
テキスト
</div>
<div class="modal-footer">
<button type="button" data-dismiss="modal">閉じる</button>
</div>
</div>
</div>
</div>
モーダルウィンドウを表示するためのボタンを作ります。
<button type="button" data-toggle="modal" data-target="#Modal1">
モーダルウィンドウを表示する
</button>
テキストに仕込むこともできます。
<a href="" data-toggle="modal" data-target="#Modal1">モーダルウィンドウを表示する</a>
モーダルウィンドウを表示する
一瞬ガタつくんですが
パソコンで見ると、モーダルウィンドウが表示される時や消える時に一瞬レイアウトが崩れているのがわかると思います。
モーダルウィンドウ表示時に背景を固定させる(スクロールを禁止する)ために overflow:hiddenを付与
→画面右端のスクロールバーが消える
→スクロールバーと同じ幅だけpadding-rightで右に余白を作る
という処理が原因と考えられます。
これを解決するために、以下のCSSを追加します。
.modal {
padding-right: 0px !important;
}
.modal-open {
padding-right: 0px !important;
overflow: auto !important;
}
overflow:autoにすることで背景が固定されなくなってしまいましたがそれはモーダルウィンドウの定義から外れているのではどうせiPhoneではもともと背景の固定ができていなかったので、まあよしとしましょう。
真ん中に表示させる
modal-dialogの部分にさらにmodal-dialog-centeredというクラスを付与することで、上下の中央に表示できます。
<div class="modal fade" id="Modal2" tabindex="-1" role="dialog" aria-labelledby="Modal2Label" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="Modal2Label">タイトル</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
テキスト
テキスト
テキスト
</div>
<div class="modal-footer">
<button type="button" data-dismiss="modal">閉じる</button>
</div>
</div>
</div>
</div>
✕ボタンを変えてみよう
右上の✕ボタンは × つまり×という文字なのですが、せっかくなのでもう少し細く、大きくしてみましょう。
擬似要素のbeforeとafterを使います。
.close::before,
.close::after {
content: "";
position: absolute;
top: 30px;
right: 30px;
width: 2px;
height: 30px;
background: #000;
}
.close::before {
transform: translate(-50%, -50%) rotate(45deg);
}
.close::after {
transform: translate(-50%, -50%) rotate(-45deg);
}
✕はいい感じになったのですが、パソコンでマウスを乗せるときの当たり判定がやや狭いので広げましょう。
以下のCSSを追加します。
button.close {
width: 50px;
height: 50px;
}
モーダルウィンドウを閉じる方法は4通りあり、
① 右上の✕
② 下の閉じるボタン
③ 背景のどこかをクリック
④ キー
おそらく閉じるボタンが一番使われているのではないかと思いますが、✕を目立つようにして、閉じるボタンはなくしてもいい気もします。
ページ読み込み時に表示
ページ読み込み時のBootstrapのmodalが思った通りの挙動にならなかったので、別の方法で実装してみます。
参考:Tech dig|JavaScriptでモーダル(ポップアップ)を表示させる方法
<div class="popup" id="js-popup">
<div class="popup-inner">
<div class="close-btn" id="js-close-btn"></div>
<img src="img/popup.jpg">
</div>
<div class="black-background" id="js-black-bg"></div>
</div>
.popup {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 9999;
opacity: 0;
visibility: hidden;
transition: .6s;
}
.popup.is-show {
opacity: 1;
visibility: visible;
}
.popup-inner {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 80%;
max-width: 600px;
padding: 50px;
background-color: #fff;
z-index: 2;
}
.popup-inner img {
width: 100%;
}
.close-btn {
position: absolute;
right: 0;
top: 0;
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
cursor: pointer;
}
.close-btn::before, .close-btn::after {
content: "";
position: absolute;
top: 30px;
right: 30px;
width: 2px;
height: 30px;
background: #000;
}
.close-btn::before {
transform: translate(-50%, -50%) rotate(45deg);
}
.close-btn::after {
transform: translate(-50%, -50%) rotate(-45deg);
}
.black-background {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.8);
z-index: 1;
cursor: pointer;
}
@media(max-width:767px) {
.popup-inner {
padding: 10px;
background-color: #fff;
z-index: 2;
}
}
window.onload = function() {
var popup = document.getElementById('js-popup');
if(!popup) return;
popup.classList.add('is-show');
var blackBg = document.getElementById('js-black-bg');
var closeBtn = document.getElementById('js-close-btn');
closePopUp(blackBg);
closePopUp(closeBtn);
function closePopUp(elem) {
if(!elem) return;
elem.addEventListener('click', function() {
popup.classList.remove('is-show');
})
}
}
このページを読み込んだ時に画像が表示されたでしょうか。
ページ読み込み時に#js-popupに.is-showを付与しています(と思います)
まとめ
背景を固定しつつ、ガタつきもなく、iPhoneにも対応した方法を引き続き探してみます。使う機会があるかはさておき
モーダルウィンドウを実装できるプラグインがいろいろあるみたいなので、そのうち試してみます。