半年前の自分が書いたjQueryで動くモーダルウィンドウをリファクタリングしてみました。
リファクタリングにあたっては以下のポイントを意識しました。
- 機能とデザインの分離 : スタイルに関することは達成可能な限りJSではなくCSSにやらせる
- パフォーマンスを意識 : JSによるDOM操作、アニメーション系メソッドなど重い実装を排除する
- アクセシビリティを意識 : マウスだけでなくキーボード操作を可能にする
- アンチパターンを排除 : 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
メソッドを使って、キーボードユーザーのユーザビリティを高めています。
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もモダンを意識して書くことは可能…ということ!
精進します。