Comment on page

Modal(モーダル)

Modal(モーダル)

実装例

今回はModalを作ってみました。まずは実装を見てみてください。
Show modal ボタンを押すと、前面にモーダル(ポップアップ)要素が表示されます。黒背景もしくはxボタンをクリックすると閉じます。それぞれサンプルコードを見ていきます。

HTML

<div class="modal-wrapper">
<div class="backdrop"></div>
<div class="modal">
<button class="btn-close">x</button>
<h3>Modal header goes here</h3>
<div class="content">
modal content goes here.
</div>
</div>
</div>
<button id="btn-show">Show modal</button>
最後の行の #btn-show の要素が見えているボタンです。それ以外の要素はデフォルトでは非表示となっています。それぞれ役割を書いておきます。
  • .modal-wrapper = モーダルの親要素。この要素のクラスをトグル(is-visibleクラスの有無の切り替えを)する事で、要素の表示/非表示を切り替えています。
  • .backdrop = 黒背景です。この要素のクリック時にモーダルを閉じる。という動きを作るためにも使われています。
  • .btn-close = 要素の右上に表示されている閉じるボタンです。
  • h3, .content = モーダルのコンテンツです。今回は文字のみのシンプルな形です。

CSS

.modal-wrapper {
/* 要素の配置を固定位置にする */
/* top, right, bottom, left のすべてが0 = 全方向に広がりきった要素 = 全面に伸びた要素となる */
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
/* 要素を非表示とする。という指定 */
display: none;
}
.modal-wrapper .backdrop {
/* 要素の位置を親要素(この場合は "fixedな.modal-wrapper")を基準とした固定位置とする。 */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
/* rgba = 赤・緑・青・アルファ値(透過) の順で色を指定。0.5なので半透明。 */
background-color: rgba(0, 0, 0, 0.5);
}
/* ".is-visible" が ".modal-wrapper" に付いたら */
.modal-wrapper.is-visible {
/* 要素を表示する */
display: block;
}
/* モーダル(ポップアップ)要素のスタイル */
.modal {
/* 要素を親要素の上下中央に位置に揃える。 */
position: absolute;
top: 50%;
left: 50%;
/* 要素をXYZ軸の順で移動させる */
transform: translate3d(-50%, -50%, 0);
/* 背景色を白に */
background-color: white;
/* 角の丸みを付ける(4px) */
border-radius: 4px;
}
.modal {
/* 要素内の空白。上下8px、左右0px(無し) の指定(略記法) */
padding: 8px 0;
}
.modal h3 {
/* 要素の外側の空白。上8px、左右0px(無し)、下0px の指定(略記法) */
margin: 8px 0 0;
/* 要素内の空白。上下左右8p の指定(略記法) */
padding: 8px;
}
.modal .content {
padding: 8px;
}
.modal .btn-close {
position: absolute;
/* 要素内の空白。上下px、左右x(無し) の指定(略記法) */
padding: 2px 8px;
top: 0;
right: 0;
/* 背景色をtransparent(= 透明)に */
background-color: transparent;
/* カーソルを "ポインター" とする */
cursor: pointer;
}
前回と比べると文量がありますが、それぞれコメントに書いた部分を見てみてください。重要な所だけ紹介します。
  • margin / padding = 何箇所か使っていますが、これは余白の空き具合の調整です。どちらも似た動きをしますが、marginは要素の外側、paddingは要素の内側の余白。を変化させます。値の指定には略記法がいくつかあり、 "8px(上下左右)" = "8px(上下) 8px(左右)" = "8px(上) 8px(右) 8px(下) 8px(左)" とどれも同じ意味となります。時計回りの順で指定する。と覚えておけば良いです。
  • position: absolute = positionを指定する事で、要素の配置方法を変更することが出来ます。以下のような種類がありますが、ほぼ未指定(= static)のまま利用することになります。
    • static(デフォルト = 未指定)
    • relative(要素同士の相対位置)
    • absolute(親からの相対位置で固定)
    • fixed(画面からの相対位置で固定)
  • transform = 要素の見た目を変形させるプロパティです。translate3d(-50%, -50%, 0) と指定すると、X軸に -50%、Y軸に-50%, Z軸に0%(= 変化なし) ずらす。という意味になります。-50%の位置は自身のサイズが起点となるので、-50% = 自身の半分の高さ(or 幅)という意味となります。 以下のようにセットで使えば上下左右の中央の位置に要素が来る。と覚えておいて(丸暗記して)ください。position: absolute; top: 50%; left: 50%; transform: translate3d(-50%, -50%, 0);

JS

/* ".modal-wrapper"の要素を取得 */
const $modal = $(".modal-wrapper");
/* ".modal-wrapper" 要素に ".is-visible" クラスを追加する。 */
const show = () => $modal.addClass("is-visible");
/* ".modal-wrapper" 要素から ".is-visible" クラスを削除する。 */
const hide = () => $modal.removeClass("is-visible");
/* "#btn-show" 要素がクリックされたら "show()" を呼ぶ。 */
$("#btn-show").on("click", () => show());
/* ".backdrop" もしくは ".btn-close" 要素がクリックされたら "hide()" を呼ぶ。 */
$(".backdrop, .btn-close").on("click", () => hide());
今回は jQuery を使いつつ実装してみました。jQueryはブラウザのDOM関連のAPIが標準化される前の時代に、作られたものですが、今でも多くのWebサイト(コーポレートページ・LP等)で利用されています。まだまだ使い道があるので、覚えておいてください。
やっている事は以下の3つのみです。
  • $("セレクタ") = まずHTML内のタグ要素への参照を取得しています。jQueryでは $("セレクタ名") とすることで、要素にアクセスする事が出来ます。
  • $.addClass() / $.removeClass() = クラスの付け替え
  • $.on("click", () => {}) = クリックイベント(要素のクリック)が発生したら、第二引数に渡された関数を呼び出す。
    • ここでは表示ボタンが押されたら show() 、閉じるボタン(もしくは黒背景)が押されたら hide() を呼び出す事で、CSSを使った要素の表示/非表示を行っています。
重要なのはJSからはクラス名の操作のみを行い、実際のモーダルの表示(表示/非表示)の切り替えはCSSで行っている点となります。こうする事で、JS/CSSでそれぞれやることの分担がハッキリします。
今回のモーダルは表示・非表示の切り替えのみでシンプルですが、実際に良く使われているBootstrapでのModal(モーダル)の実装はこのようになっています。
BootstrapのModal(モーダル)のサンプル
今回作ったものと比べると、背景・ポップアップ部分のトランジション(上からスライドインして、閉じると上にスライドアウトする)の有無が違いとして挙げられます。この動きをどうやって再現するか、についてはまた後ほどVue.jsのサンプルでご紹介しようと思います。
このように自分が作ったものと良く使われているものを比較して、「どうやったらこの動きが作れるんだろう」と興味を持つ。あるいは何が足りないかの差に気づける事が、知識を深める上で大事なポイントです。
最後に複雑なコンポーネントである Tab(タブ)要素 の事例を見ていきます。