6
4

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-03-27

半年前の自分が書いた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もモダンを意識して書くことは可能…ということ!

精進します。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4