slowjet

is a part of a carburetor

Flexible BoxでGrowlみたいな通知UIを実装する

f:id:nori_17:20130301015943p:plain

↑の画像のみたいなGrowlぽい通知UIを作るときに、一筋縄ではいかなそうなところと言えば右上から下へ順に流れていってウィンドウに収まりきらなくなったら、列が変わって左へ流れていくようなレイアウトを作るところでしょうか。言葉が下手すぎたので図を見てください・・・

f:id:nori_17:20130228215409p:plain

こういうやつ。

CSS力がめっきり減ってきてるので、確かこういうやつCSSで出来たと思うんやけどなーぐらいの感じだったんですけど、これこそFlexible Boxですね。

Flexibile Boxの詳細はわざわざ説明するのもアレなので以下の仕様書とかサイトを見て把握すればいいと思います。

HTML

<div class="mod-notifications">
  <div class="mod-notifications-notif"></div>
  <div class="mod-notifications-notif"></div>
  <div class="mod-notifications-notif"></div>
  <div class="mod-notifications-notif"></div>
</div>

CSS

Chrome25で動くようにしか書いてません

.mod-notifications {
  /* ここからFlexibile Box */
  display: -webkit-flex;
  /* directionをrowにすると行並びに */
  -webkit-flex-direction: column;
  /* 右から左へ改列しつつ並べたいので wrap-reverseを指定 */
  -webkit-flex-wrap: wrap-reverse;
  /* 上詰めは flex-start */
  -webkit-justify-content: flex-start;
  /* 右詰めは flex-start */
  -webkit-align-content: flex-start;

  padding: 10px;
  /* 上下padding10pxずつを100%から引くとちょうどになるのでcalcを使いましょう */
  height: -webkit-calc(100% - 10px * 2);

  /* 通知は画面の一番手前に表示されるべき */
  position: fixed;
  top: 0;
  right: 0;
  z-index: 10000;
}

.mod-notifications-notif {
  /* 優先度とかはない */
  -webkit-flex: 1 1 auto;

  /* 幅は300pxで固定、flex-boxはheightが有効にならないので
  min-heightとmax-heightで指定する
  が、コンテンツ量が少なくてもmin-heightに従うわけではない */
  width: 300px;
  min-height: 50px;
  max-height: 50px;

  margin: 10px 0 0 10px;
  border: solid rgba(0,0,0,.3) 1px;
  border-radius: 5px;
  padding: 10px 0;
  overflow: auto;
  position: relative;
  background-image: -webkit-gradient(linear, center top, center bottom, from(#f4f6f7), to(#e1e3e5));
  box-shadow: 0px 0px 15px rgba(10,10,10,.3), 1px 1px 1px #fff inset;
}

で、まあこれだけだと通知エリアが通知がいっぱい出たときとか画面一番手前全面に広がったりして、下にあるコンテンツがクリックできなくなる。

f:id:nori_17:20130301012805p:plain

Pointer Events

まあでもそれが出来ないのは昔の話で。なるほどのPointer Events。これも解説するのもアレなんで仕様書を読んでもらうとして・・・

ここでやることを超絶ざっくりいうと、指定した要素に対するクリックとかのイベント全般を殺せる(レイヤー自体存在してないように振る舞える)。

今の例でいくと、.mod-notificationsは存在しないように振る舞いたい、でも.mod-notifications-notifは存在させたい。

Pointer Eventsを使えば超簡単

.mod-notifications {
  pointer-events: none;
}

.mod-notifications-notif {
  /* 何も指定しないと親(.mod-notifications)の
  Pointer Events を継承して none になっているので auto にする */
  pointer-events: auto;
}

コードとデモ

次はこのNotificationsで、BackboneのViewを使ったやつとかやる気があれば書きます。