Edited at

jQueryモーダルウィンドウをリファクタリング

More than 1 year has passed since last update.

半年前の自分が書いたjQueryで動くモーダルウィンドウをリファクタリングしてみました。

リファクタリングにあたっては以下のポイントを意識しました。


  1. 機能とデザインの分離 : スタイルに関することは達成可能な限りJSではなくCSSにやらせる

  2. パフォーマンスを意識 : JSによるDOM操作、アニメーション系メソッドなど重い実装を排除する

  3. アクセシビリティを意識 : マウスだけでなくキーボード操作を可能にする

  4. アンチパターンを排除 : 3.のキーボード操作実装にあたって、同じ記述の繰り返しを避ける(DRY原則)

というわけで完成したモーダルはこちらです。

See the Pen jQuery Modal by Hibiki Kudo (@h_kudo) on CodePen.

動きも軽快でキーボードでも操作できる。いい感じです。

以下簡単に説明です。


機能とデザインの分離 : スタイルに関することは達成可能な限りJSではなくCSSにやらせる

従来モーダルの中央寄せはJSで計算して描画していましたが、中央寄せはCSSだけで実装できます。またその他のスタイル実装においても.cssメソッドを使わず、なるべく.addClass, .removeClassメソッドを用いてCSSクラスを変更する形にします。


before.js

$(window).resize(centeringModal);

function centeringModal() {
var width = $(window).width();
var height = $(window).height();
var cWidth = $("#modal-content").outerWidth();
var cHeight = $("#modal-content").outerHeight();

$("#modal-content").css({
left: (width - cWidth) / 2 + "px",
top: (height - cHeight) / 2 + "px"
});
}



after.css

.modal__content{

width: 500px;
min-height: 220px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}


パフォーマンスを意識 : JSによるDOM操作、アニメーション系メソッドなど重い実装を排除する

従来は.append, .removeメソッドを使ってモーダル背景を直接DOM操作していましたが、これはパフォーマンス的に重いので思い切ってHTMLにモーダル背景を置きっぱなしにし、この表示・非表示を切り替えるのみにする形にしました。

また、処理の重い.fadeIn, .fadeOutなどのアニメーション系メソッドを非使用とし、アニメーションはもっぱらCSSのtransitionプロパティにやらせます。


before.js

$( "#modal-content" ).fadeIn();



after.js

$( "#modal-content" ).addClass(".is-visible");



after.css

.modal__content.is-visible{

opacity: 1;
visibility: visible;
transition:visibility .3s ease, opacity .3s ease;
z-index: 1002;
}


アクセシビリティを意識 : マウスだけでなくキーボード操作を可能にする

基本的には.onイベントに.clickだけでなく.keydownを追加するだけなので意外と簡単。

他にはtabindex属性をこねこねしたり.focus,.blurメソッドを使って、キーボードユーザーのユーザビリティを高めています。

モーダル・オーバーレイは置きっ放しにするためスクリーンリーダー・ユーザーなどにとって邪魔な要素となりますが、role="presentation"aria-hidden="true"を追記することでアクセシビリティを担保させています。


afterVer1.js

const $modalOpen = $(".js-modal-open");

$modalOpen.on("click", function(e) {
/* 処理 */
});

$modalOpen.on("keydown", function(e) {
if (e.keyCode === 13) {
$(this).trigger("click");
}
});



アンチパターンを排除 : 3.のキーボード操作実装にあたって、同じ記述の繰り返しを避ける

キーボード操作を追加するだけなら確かに簡単でしたが、上記のafterVer1.jsでは.onメソッドを繰り返し書いてしまっています。連想配列を使ってよりすっきりと記述することができました。


afterVer2.js

const $modalOpen = $(".js-modal-open");

$modalOpen.on({
click: function() {
/* 処理 */
},
keydown: function(e) {
if (e.keyCode === 13) {
this.trigger("click");
}
}
});



所感


  • パフォーマンスは体感的に向上してるんですが、今回ちゃんと計測してません(次こそは)。

  • CodePen埋め込み良い。

  • 我々がその気になればjQueryもモダンを意識して書くことは可能…ということ!

精進します。