ワシはワシが育てる

週刊少年ジャンプと任天堂のゲームが三度のメシより好きです。

モーダルウインドウを閉じるためのJS+マークアップ

モーダルウインドウを表示した時、閉じるボタンとは別に画面外クリックでも閉じるよう設定したい場合。

Stack Overflowの回答などでは画面外クリックについて、HTMLごとイベントリスナーを登録しておき、モーダルウインドウの画面内ではイベントの伝播を停止するという方法をよく目にします。

具体的には下のようなコードだ。

$('html').on('click', function () {
  $('#modal_window').fadeOut();
});

$('#modal_inner').on('click', function(event) {
  event.stopPropagation();
});

多くの場合このコードで問題なく動きますが、stopPropagation()はモーダルウインドウの非表示以外のイベントも問答無用で止めてしまうので注意が必要。

後からイベントを追加するようなことがあれば不具合の元になるし、なによりメンテナンス性が悪くなります。

 

キッチリ画面外クリックを判定するためには、別途画面外領域というのを設けてあげると良いでしょう。

f:id:washiiku:20131110071845g:plain

 

画像では微妙に余白がありますが、実際は灰色の領域も画面全体を覆っており、灰色の領域をクリックすると画面全体のモーダルウインドウを閉じます。

 

マークアップは以下のようになります。

<div id="modal_wrapper">
  <div id="modal_close_area">
  </div>
  <div id="modal_inner">
    コンテンツを配置
  </div>
</div>

 

続いてCSSは以下のように。

#modal_wrapper {
  position: fixed;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
  z-index: 2;

  #modal_close_area {
    position: fixed;
    left: 0px;
    top: 0px;
    width: 100%;
    height: 100%;
    z-index: 9;

  }

  #modal_inner {
    width: 600px;
    margin: 0 autp;
    z-index: 99;
  }
}

 

そんでJavaScriptは以下のように。

$('#modal_close_area').on('click', function () {
  $('#modal_wrapper').fadeOut();
});

 

ポイントは3つの領域にそれぞれz-indexをつけて前後の配置を明確にすることです。

それによりコンテンツ外=画面外という意味付けとなり、わざわざイベントの伝播を止めなくてもモーダルウインドウを閉じることができます。

 

冷静に考えれば物凄く単純な問題ですが、自分は以前延々と考えこんでしまったことがあるので、参考になれば幸いです。