半年前の自分が書いた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メソッドを使って、キーボードユーザーのユーザビリティを高めています。

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もモダンを意識して書くことは可能…ということ!

精進します。

元記事はこちら

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