jQuery と CSS を使った Apple 風パンくず

Fig 1: 「jQuery と CSS を使った Apple 風パンくず」完成図

パンくず (Breadcrumbs) ってその必要性に疑問を感じることの多い要素の筆頭だと思う。この案件で要るか、これ? みたいな。そんなわけだからあまり力を入れて作ったことがなかったんだけど、Veerle’s blog のパンくず作成チュートリアル Simple scalable CSS based breadcrumbs を読んで、必要かどうかはとりあえず置いといて、どうせ置くならお洒落な方がいい、っていうか俺もクールなパンくず作る! と盛り上がってしまい、作ってみた。

Fig 2: Apple のパンくず。影響力大
Fig 3: Delicious のタグのリスト。妙に好き

目論んだイメージとしては Apple 風のルックスに Delicious のチェーン状に繋がったタグのリスト的なロールオーバー効果をプラスした感じ。もちろん、カスタマイズの余地を十分に残しつつ、できる限りシンプルなコードを目指した。

1. マークアップ

パンくずをどうマークアップするか、というのはよく議論される話題。ちなみに前述の Veerle’s blog では ul、Apple は ol だ。でも俺に言わせりゃんなもん p に決まってんだろ、である。パンくずってのはあくまでも「迷子にならないための道しるべ」であるべきだと思うから、なんというかこう「1 本につながった感じ」が欲しいんだよね。リスト形式だと 1 つ 1 つのパンくずが独立しちゃってる気がして、どうにも違和感を感じるというか。そういった意味では ol ってのはまあアリかなと思うけど、でも実際のところ横一列に並べる以外の見せ方ってなかなか考えづらいわけで、そうするとやっぱ p じゃね、てのが僕の考え方だけどどうだろう。

まあとにかく、ここではパンくず全体を p 要素でマークアップする。各リンク間を「>」 (>) で区切って、「今ココ」は em で示す:

<p class="crumbs">
  <a href="#">Home</a><span> &gt;
  </span><a href="#">Archives</a><span> &gt;
  </span><a href="#">2009</a><span> &gt;
  </span><em>You Are Here!</em>
</p>

「>」はコントロールしやすくするため span で囲んでおく。このとき前後の要素との間にスペースを入れないように。マークアップは以上。次、スタイルシートいきます。

2. スタイルシート

p.crumbs {
  font-family: "Lucida Grande", "Verdana", sans-serif;
  font-size: 68.75%;
  line-height: 3.0;
  font-weight: bold;
  background-color: #e0e0e0;
  overflow: hidden;
}

まずは p を整形。line-height は Apple っぽくやや大きめに。だいたい 3 前後ぐらいがサマになると思う。overflow につては後述。次は aem をまとめて指定:

p.crumbs a,
p.crumbs em {
  padding: 1.0em 2.0em 1.0em 1.0em;
  color: #404040;
  background-color: #e0e0e0;
  text-decoration: none;
  font-style: normal;
}
p.crumbs a:hover {
  color: #ffffff;
  background-color: #808080;
}

まず padding を設定して領域を広げる。もし pline-height3 にしたなら、a の上下 padding はそれぞれだいたい 1em。もし上下に少しはみ出しても前述のとおり poverflow を指定しとけば OK。また右だけ少し多めに取るのもポイント。

背景色は p と同じに。a:hover のデザインはここでは Delicious を意識しつつかなりざっくりとした反転パターンを採用したけど、実際はもう少し抑え気味のほうがおしゃれかな。

さて次はいよいよこのデザインのキモ、「>」部分にギミックを仕込む:

p.crumbs span {
  padding: 1.0em 0;
  margin-left: -1.5em;
  color: #e0e0e0;
  background: url(img/crumbs.png) no-repeat 100% 50%;
}

まず上下の paddinga と同じ値を指定。margin-left にマイナス値を指定し、直前の a 要素の上に重ねる。値の大きさはフォントによって調整が必要かも。また前景色を a の背景色と同じにして見えなくする。

Fig 4
Fig 5

背景画像は、Fig 4 のように右向きの三角部分を透過させ、かつその境い目の部分にラインを入れたものを用意。文字サイズに対応すべくやや大きめに。GIF でもいいんだけど、IE6 への対応は別途考えるとして、ここはぜひ半透明のアルファチャネル PNG でいってみよう。ついでに Fig 5 のようなロールオーバー用も作っておく。

さて、ここまでのソースをブラウザで見てみると、ぱっと見たところは出来上がったけども、リンクにマウスの乗せると Fig 6 のようにイマイチな結果になるはずだ。

Fig 6: もう一息

ここで要求される挙動はどんなものだろうか? a:hover 状態になったときに「直前の span の背景画像」と「直後の span の前景色」が変更できればいいよね。はい、jQuery の出番です。

3. スクリプト

<script type="text/javascript" src="js/jquery.js"></script>

HTML/XHTML の head で jQuery を読み込み、さらに以下のような JavaScript を加える:

$(function() {
  $('p.crumbs a').hover(function() {
    $(this).prev('span').addClass('prev');
    $(this).next('span').addClass('next');
  }, function() {
    $('span.prev').removeClass('prev');
    $('span.next').removeClass('next');
  });
});

hover() イベントはその要素にマウスが乗ったときと外れたときに実行する関数を定義する。ここでは a にマウスが乗ったときに、prev() でその直前の、next() で直後の span を取得、それぞれに class を付与し、マウスが外れれば削除する、という関数。今回のマークアップ例でいうと、たとえば「2009」ってリンクにマウスが乗っている間、ソースは JavaScript エンジンによってこういうふうに生成されていることになる:

<p class="crumbs">
  <a href="#">Home</a><span> &gt;
  </span><a href="#">Archives</a><span class="prev"> &gt;
  </span><a href="#">2009</a><span class="next"> &gt;
  </span><em>You Are Here!</em>
</p>

あとはこの新たに生成された class のためのスタイルを書けばいい。

4. 再びスタイルシート

p.crumbs span.prev {
  background-image: url(img/crumbs-h.png);
}
p.crumbs span.next {
  color: #808080;
}

はい、出来上がり! 完成版のデモ をどうぞ。

最後に背景画像について補足が 2 つ。まず、前もって読み込みを行っていないので最初にマウスを乗せたときに「ちらつき」が発生する。なんか対策したいところ。例えば p 要素あたりに持たせてしまっても良いかも:

p.crumbs {
  ...
  background: #e0e0e0 url(img/crumbs-h.png) no-repeat -9999px -9999px;
  ...
}

もうひとつ、IE6 がアルファチャネル PNG に対応していない件について。デモ では CSS のハックで IE6 のみに代替の透過 GIF をあてがってるけど、もちろん適当な JavaScript ライブラリかなんかを使っても良い。というかその方がキレイだし。ハッピィ・ヴァレンタイン!