ezorisu-web

ウェブサイトのデザインとかお仕事の効率化とか

CSSでドロップダウンメニュー

このブログを作るに当たって、いろいろと試行錯誤をした記録です。すぐ忘れてしまうので、覚書として書き留めています。今回はヘッダーのメニュー編。

CSSのドロップダウンメニューです。テストバージョンのオリジナルWordPress Themeで一部表示がおかしくなっているところがあったので、少し整理してみました。
ヘッダー部分に横並びメニューとしてデザインしていて、メニュー項目にカーソルを合わせると階層式に子メニューが表示される、よく見るタイプです。

まずはメニューなのでリンク項目であることを前提に、リストとしてマークアップします。(DEMOではリンク部分でも別のページに飛ばないようにしています)

[sourcecode language=’html’]

[/sourcecode]

1段目は横並びのメニュー項目で、2段目以降は入れ子構造にしていきます。

次はCSS。
まずは、ドロップダウンメニューとしての基本形。

[sourcecode language=’css’]
#menu-sample ul { /*リスト全体*/
list-style: none;
margin: 0;
padding: 0;
}

#menu-sample li { /*リストの1段目*/
float: left;
min-width: 94px;
white-space: nowrap;
}

#menu-sample ul ul { /*2段目以降*/
display: none;
position: absolute;
z-index: 10;
}

#menu-sample li li { /*2段目以降のリスト項目*/
clear: left;
position:relative;
width: 100%;
}

#menu-sample ul ul ul { /*3段目以降*/
top: 0;
left: 100%;
}

#menu-sample ul li:hover > ul {
display: block;
}

*+html #menu-sample ul ul a { /*IE用*/
width: 72px; /*(94-10-10-1-1)パディングとボーダーの分を引いた値*/
white-space: normal; /*幅に応じて改行*/
}
[/sourcecode]

ul:リストの装飾は不要なので削除。マージン、パディングも0にして、いったんきれいな身体に。

1段目のliをfloat: leftで横並びにします。
できればひとつひとつのメニュー項目の幅をそろえたいと思いますが、文字数によってはピッタリ納まるとは限らないので、あくまでも最小幅とし、文字数が増えても対応できるようにしておきます。それがmin-width: 94px部分。94pxはヘッダーの幅と入れたいメニュー項目数から逆算して適当に決めた数値。
white-space: nowrapは下層のメニュー項目も改行しないようにしています。これを入れておかないと3段目以降で固定幅になって、文字が改行されてしまいます(なぜなのかよくわからない)

ul ulはメニューの2段目以降を指定しています。ここで下層のメニューが見えないようにdisplay: noneで 非表示にします。
positionの使い方がわかりにくいですが、ul ulにposition: absoluteを指定して、2段目以降のulにabsoluteがかかるようにします。2段目のulの親要素である1段目のliにはpositionが指定されていないので、親要素の下に絶対配置されます。
z-index: 10は念のため。サイドバーなどにメニュー項目が重なったとき、下になって隠れてしまう場合もあるので。

2段目以降のリスト項目li liはclear: leftで縦並びに戻します。
position:relativeを入れて2段目以降のリスト項目左上を基準とします。
width: 100%は、リスト項目どれかの文字数が多いときにそれに合わせて同じ幅になるようにしています。

3段目以降を示すul ul ulにもabsoluteがかかっていますが、親要素である2段目以降のliでposition:relativeを指定してあるのでその要素の左上が基点となり、子要素であるulにtop、leftなどで基点からの位置を指定します。
ここではtop: 0でliと下段のulのラインを揃えて、left: 100%で親要素のul幅分右へずらしています。
4段目、5段目と階層が増えても、親要素、子要素の関係は変わらないので同じように表示されます。

あとは、li:hover > ul で子要素がある項目にカーソルが重なったときに直下のulをdisplay: blockで表示するようにします。

例によって、IE用の対策。

まずIEではli liでwidth: 100%を指定してもなぜか最大幅のメニュー項目に合わせて同じ幅に広がってくれないので、*+htmlハックでIE用にメニューの幅を固定して改行するように指定してます。
他のブラウザと見た目が少し変わりますが読めるから大丈夫、というレベルで対応。

そもそもIE6は疑似クラスの :hover や min-width が効かないので、「Google Code」の「IE7.js」を使わせてもらいます。

htmlのhead部分に

[sourcecode language=’html’]

[/sourcecode]

を書き込むだけです。

IE6は、しょうがないから最低限の対応だけしておくか、というスタンスなのでご勘弁を。
これに関しては、「なるべくならIE用のHackは使いたくない」と「「IE7.js」で IE6 でも透過 PNG、疑似クラス :hover に対応」を見てください。
上記の*+htmlハック部分も「IEの条件付きコメント」を使って別ファイルにしたほうがスッキリします。

あとは、メニューっぽく装飾を施します。

[sourcecode language=’css’]
#menu-sample li {
margin-left: 3px;
}

#menu-sample a { /*1段目以降のメニュー文字*/
font-size: 13px;
line-height:15px;
color: #dadada;
text-decoration: none;
text-align: center; /*1段目は文字を中央合わせに*/
padding: 5px 10px;
background-color: #242424;
display: block;
}

#menu-sample a:hover {
color: #f90;
background-color: #111;
}

#menu-sample ul ul {
padding-top: 2px;/*2段目を少し下げた*/
}

#menu-sample ul ul ul { /*3段目以降*/
padding-top: 0; /*2段目のパディング2pxを元に戻す*/
}

#menu-sample li li {
margin-left: 0; /*liのmargin-left: 3pxを元に戻す*/
}

#menu-sample ul ul a { /*2段目以降のメニュー文字*/
font-size: 11px;
line-height: 1.3;
text-align: left; /*2段目以降は左寄せにもどす*/
border-top: solid 1px #555555;
border-right: solid 1px #070707;
border-bottom: solid 1px #070707;
border-left: solid 1px #555555;
background-color: #343434;
}
[/sourcecode]

文字色やバックグラウンドの色は、メニュー内のa要素で指定。display: block;でブロック要素にしてサイズを固定します。
a:hoverでカーソルが乗った位置がわかるように文字色とバックグラウンド色が変わるようにします。
2段目以降は文字サイズを少し小さくしてみました。
その他諸々の指定は、個人個人の好みの問題です。

ただ、やっぱりIEが絡んでくるとなかなかうまく表示されない場合もあって、たとえば2段目と3段目で少し隙間を空けようかとか、逆にちょっと重ねてみようかと思うと、細かいところでいろいろ苦労をすることになります。Operaも少し挙動が変になったりします。

とりあえずこのサンプルでは、その辺も考えた上での基本形ということで IE6,7,8、Opera、Firefox、Safari それぞれのブラウザであまり苦労をしないで動くような最低限のデザインにしてあります。

あとは応用ですので、バックの色やボーダー、イメージ画像を使ったりしていろいろバリエーションを楽しめると思います。

参考サイト

コピーライトをフッターエリアの中央に入れたい

このページの一番下にフッターエリアがあります。最近のフッターは、いろいろ情報を詰め込んでいるものも多くなりましたが、このサイトではシンプルにコピーライトだけ。
スッキリ見せたいので、フッターは少し色を変えて、真ん中に簡潔なコピーライト。

この真ん中に文字を表示するというのを考えてみました。文字を特定のエリアで縦方向の中央寄せにする。

左右の中央に合わせるのは、簡単。次は上下の中央合わせ。ここで、ハテ?と行き詰まってしまった。
今まで、自分のサイトならコピーライトの文字数も行数も自分で決められるから、それに合わせて調整するのは比較的簡単でしたが、
一応フリーテーマで公開するものを作ろうと思ったら、これがなかなか難しい。
使う人によって一行なのか複数行なのかまちまちだろうから、どちらでも対応できるようにしておきたい。
さて、どうしたものか。

調べてみると、ヨモツネットというサイトの「CSS で簡単に上下中央揃えを実現する」という記事の方法が使えそうです。
要は、コピーライトを入れる要素にdisplay:table-cell;を指定することによってテーブルセルと見なす。そうするとそのセル内ではインライン要素である文章もvertical-alignを使って中央合わせが出来るようになる。なるほど、簡単。

とにかく、フッター用の標準のパターンとして考えてみた。

一行の場合

二行の場合

HTML<div class="footer-sample">
<div class="copyright-sample">コピーライトの例です。コピーライトの記号と年数、著作者名を入れます。</div>
</div>

“footer-sample”というクラス名のdivのなかに”copyright-sample”というクラス名を付けたdivを入れて、その中に実際のコピーライトを書きます。

CSSdiv.footer-sample {
    background-color:#333;
    height:70px;
    width:500px;
    display:table-cell;
    vertical-align:middle;
    text-align:center;
}

div.copyright-sample {
    color: #ccc;
    font-size: 12px;
    line-height: 1.2em; 
}

フッターエリアを黒っぽく塗りつぶして、とりあえず高さは70px、幅は500px。
display:table-cell;を指定をしてフッターをテーブルセルとみなしてしまう。あとはテーブルセルとして中央寄せを設定してあげる。

一般的なブラウザーだとこれだけでOK。シンプルでスッキリ。
ところがいつものように、IEだけは、display:table-cell;に対応していない、と。
いいかげん、IEなんか使うのやめようよと言いたいのをぐっとこらえて、IE用も。

HTML<div class="footer-sample">
<!--[if IE ]>
    <span class="dummy-h"></span>
<![endif]-->
<div class="copyright-sample">コピーライトの例です。コピーライトの記号と年数、著作者名を入れます。</div>
</div>

IEで開いたときだけ、”dummy-h”というクラス名を付けたspanを読み込むようにして、IEの場合はここで行数の違いを調整できるようにする。

CSSdiv.footer-sample {
    background-color:#333;
    height:70px;
    width:500px;
    display:table-cell;
    vertical-align:middle;
    text-align:center;
}

div.copyright-sample {
    color: #ccc;
    font-size: 12px;
    line-height: 1.2em; 
}

*:first-child+html div.copyright-sample {
    display:inline;
    zoom:1;
    vertical-align:middle;
}

*:first-child+html div.footer span.dummy-h {
    display:inline;
    zoom:1;
    height:100%;
    vertical-align:middle;
}

* html div.copyright-sample {
    display:inline;
    zoom:1;
    vertical-align:middle;
}

* html div.footer span.dummy-h {
    display:inline;
    zoom:1;
    height:100%;
    vertical-align:middle;
}

*:first-child+html はIE 7用のハック。* html はIE 6用のハック。
IEには、display:table-cell; が効かないので、別の方法で同等の効果を与えています。
(これに関しては、上記のヨモツネットさんの記事がたいへん参考になります)
同時にダミー要素の span に height:100%; 高さを与えて、複数行でも対応できるように。この辺のことはネットをあっちこっちあさっていて、どこかで見た方法ですが、いろいろ試しながらやっているうちに、どこで見たのかわからなくなってしまいました。

一行の場合(IE対応版)

二行の場合(IE対応版)

IEの人もちゃんと表示されてるかな?

参考サイト

Firefoxでリンクをクリックしたときの点線を消す

前から気になっていたんだけど、意外と簡単。CSS で点線表示を消してやるだけ。

CSSa:focus{
outline:none;
}

または、

CSSa {
outline: none;
}

どちらの書き方でもOK。MacでもWinでも消せます。IEでも同じようにクリックしたときに点線が表示されますが、こちらは消えてくれませんでした。