ハックやJavaScriptを使わず、クリーンHTMLでIE6にも対応したプルダウンメニュー

カテゴリ:CSSテクニック 2009年9月30日 18:11

まことさんからコメントをいただきましたが、ul.sub li の overflow: hidden; がなければIE7(IETester)でも動きましたよー。とのことでした。まだこちらで検証していないんですが、もし問題が出ている人がいたら、こちらを試してみてください。

コメントを頂いて気づいたのですが、IE7 ではどうやらうまく動いていないようです・・。CSS Play のほうではうまく動いているので、こちらのサンプルの不備だと思われます。改善するまでは概念の理解にとどめておいてください・・。

最近紹介ばかりな感じがしますが・・。
ちょっとテクニックの発想に感動したので、解説も踏まえて紹介したいと思います。
ちなみにこのテクニックの元になったのはこちらの CSS Play で紹介されているものです。

まず最初に、概念図を見せます。(クリックで拡大)
クリーンHTMLのプルダウンメニュー概念図

クリーン HTML のプルダウンメニュー デモ

サンプルダウンロード

ネガティブマージンとパディングで余白を相殺

概念図を見てもらうと分かりますが、通常のメニューに対して margin-top にネガティブマージンを、 IE6 で対応している数値いっぱいに設定し、かつ同様の値を padding-top にも設定します。
"モダンブラウザの場合はこれはなくても大丈夫なのですが、IE6 の場合、隠れているプルダウンメニュー部分が隣の要素と重なる、という不具合があるのでこれで解消しています。"

メニューに固定幅と overflow: hidden を設定

そしてリスト要素に対して表示させたい固定幅を指定しつつ、overflow: hiddenではみ出した部分を非表示にします。ここがまずポイント 1 です。

メニューとプルダウンメニューを float で配置

続いて、リスト内の a 要素を左に float させ、プルダウンでマウスオーバー時に表示させたい要素も左に float させます。
これで、なにもしていなければ、単純に最初の a 要素とリスト要素が横に並ぶ状態になります。

ここでポイント 1 が生きてきます。固定幅と overflow: hidden によって、float で並んだ要素のうち、a 要素のみが表示されます。2 カラムのサイトで、右カラムだけ overflow: hiddne で隠れているのを想像すると分かりやすいと思います。(イメージはこんな感じ↓)
overflow: hidden で消えているイメージ図

:hover でボックスのサイズを変更

ここがポイント 2 です。そして秀逸。
:hover 擬似クラスは IE6 の場合、a 要素以外には対応していません。
無理やり対応させる方法がなくはありませんが、その場合は HTML 的に invalid になってしまいます。
しかし、今回はタイトルの通りクリーンな HTML 実装されているため、しっかりと a 要素に :hover 擬似クラスを使います。

では使われているポイントを見てみましょう。

しっかりと a 要素に :hover 擬似クラスが使われています。
ここで指定されているmargin-right: 1pxは、プルダウンメニューの親(マウスオーバーしたらメニューが表示される部分)の右マージンを拡大する、という処理です。

ではなぜ、こんな処理をしているのでしょうか。
答えは、これを追加することによって、上で書いた overflow: hidden で隠れているリスト要素を "カラム落ちさせる" ことです。
ぴったりと計算したカラムの場合、1px でも width なり margin なりが違うとカラム落ちしてしまいますよね。
これを "あえて" 実行しているわけです。

さて、カラム落ちしたリストはどうなるでしょうか。
overflow: hidden で隠れるのは、幅の部分のみなので当然、カラム落ちしたリスト要素は、マウスオーバーした a 要素の下に来ます(カラム落ち)。

まさにプルダウンメニューが表示されたように見えますね。
しかし、これだけではリスト部分にマウスを移動した瞬間、a 要素のmargin-right: 1pxがなくなってしまうため、また元の位置に戻ってしまいます。

ここが秀逸な部分です。
リスト部分にマウスを持っていくと、当然その先もリンクになっています。
リンクということは a 要素ですよね。
そして、この a 要素にも同じようにボックスのサイズが変わる処理をしておきます。
こんな感じです↓

すると、親に当たる a 要素からマウスが離れても、今度は子要素に当たる a 要素の幅が変わるため、結果的にプルダウンで表示された部分にマウスを移動してもプルダウンしたままになる、というわけです。

さらに秀逸な点

さて、これでテクニックの肝は説明しましたが、このサンプルにはさらに秀逸な点があります。
それは "クリックしてプルダウンを固定することができる" ということです。

上の CSS を見て気づいている人もいるかもしれませんが、ul.sub a:focusul.sub a:activeにもmargin-right: 1pxが設定されているため、クリックした際にも margin-right: 1px が反映されます。

そのため、クリックするとプルダウン状態が維持される、というわけです。
これを応用すると、クリックで表示させるメニューも簡単に作れそうですね。

注意点

このテクニックの注意点というか、対応できない点として、リストの幅が固定でないといけないため、2 階層以上あるようなプルダウンメニューは作成できません。そのため、ちょっとしたプルダウンなどに使うことが望ましいです。

この記事のカテゴリー一覧を見る⇒CSSテクニック

トラックバックURL

http://css-eblog.com/cgi-bin/mt/mt-tb.cgi/158

コメント

1 - 匿名 さん

IE7は未対応ですか?
確かにIE6にも対応という記述だけど・・・。
いくつかのPCで試しましたがIE7では無理でした。
実装の途中で気づいたので先に明記してほしかった。。

2010年4月26日 12:37

2 - えど Author Profile Pageさん

おお・・IE7で見ると表示されないですね・・。
参考にした CSS Play では正常に表示されているので、IE7 でも問題ないはずです。
ちょっとざっと見てみたところ、隠れている ul 要素(class="sub" のもの)に
width を明示するとおそらくうまく行くと思います。

内容については後ほど追加しておきます。申し訳ないです。
可能であれば、上記を試してもらえますでしょうか。

2010年4月26日 14:21

3 - 匿名 さん

回答ありがとうございます。
ご指摘通りにwidthを入れるとMO時に表示は出ますが、隠れた部分にマウスを乗せると消えますね。
また、同様の処理ではFFなどで逆に動かなくなりました。
CSS Playのものに同様の処理をしても動かなくなります。
お助けを。。。

2010年4月26日 16:16

4 - まこと さん

横から失礼します。
ul.sub li の overflow: hidden; がなければIE7(IETester)でも動きましたよー。
気づかないところで別の問題が発生してるかもしれませんが一応報告です。

2010年5月31日 02:20

5 - えど Author Profile Pageさん

>>まことさん
コメントありがとうございます!
なるほど、それで問題なさそうなんですね。
貴重な書き込みありがとうございます。

ちょっと自分のほうでは時間がなくて試せていないのですが、
時間があったらこちらでも検証したいと思います。
ありがとうございました!

2010年6月 1日 12:37

6 - 匿名 さん

一つご質問をよろしいでしょうか。
上記の"クリックしてプルダウンを固定することができる" とありますが
逆に、クリックするとプルダウンが閉じる、とするには
どのような設定を行なえばよろしいのでしょうか?

2010年6月19日 17:57

7 - えど Author Profile Pageさん

コメントありがとうございます!
記事に書かれているものは、クリックしたときに固定するというより、
マウスオーバー時と同じことをクリックしたときに実現しているものになります。

なので、もう一度クリックしたら閉じる、というのは実現できません。
(もちろん、JSを使うのであれば可能ですが、記事の趣旨とは版するので・・)

2010年6月20日 23:41

コメントを投稿





承認されるまでコメントは表示されません。しばらくお待まちください。