2010-03-23

display:inline-block; を使う

要素の横並びに float:left; ではなく display:inline-block; を使うためのメモ。
元ネタは、CSS display: inline-block: why it rocks, and why it sucks

※ 2011年4月12日追記: 暫定版ですが、新しい方法を書きました。display: inline-block を使う(修正版)

float:left; で横並びにしようとしたとき、各要素の高さが違うと

このようになってしまいます。
カッコ悪いですよね…。というよりデザイン通りになっていません。

display:inline-block; を使うと、

このようになります。素晴らしい!エクセレント!
display:inline-block; には、text-align および vertical-align が指定できるので、今まで面倒だったレイアウトが簡単に実装できるようになります。

と、そう簡単にはいきません

記述もシンプルになるし、変な崩れも起こらないし、完璧だー!なんていうふうに特に何も考えずにコーディングすると、IE6、IE7 以外で隙間が生まれてしまいます。

先に出した成功例は、以下に示す解決法を実践したものだったのです…。
何も対応をしなかった場合、IE6、IE7 以外ではこのようになってしまいます。

今回基準となるコードは以下。

ul{
}

li{
    width: 100px;
    vertical-align: top;
    display: inline-block;
    /display: inline;
    /zoom: 1;
}
<ul>
<li>inline-block のサンプル 1</li>
<li>inline-block のサンプル 2</li>
<li>inline-block のサンプル 3</li>
<li>inline-block のサンプル 4</li>
</ul>

この隙間の原因は改行
試しに改行を消してみるときれいに隙間が埋まります。

解決法は大きく分けて2つ。
HTML で直すか、CSS で直すかです。

解決法 1: HTML 側で直す

解決法 1-1: 改行を削除

そのままですね。
改行コードが原因なので、改行を削除してしまえば隙間が埋まります。

<ul>
<li>inline-block のサンプル 1</li><li>inline-block のサンプル 2</li><li>inline-block のサンプル 3</li><li>inline-block のサンプル 4</li>
</ul>

問題は、横並び要素を1行にまとめて書くので、ソースの可読性が低下する可能性が高いこと。

解決法1-2: コメントアウトを使う

よくある解決法ですね。

<ul><!--
--><li>inline-block のサンプル 1</li><!--
--><li>inline-block のサンプル 2</li><!--
--><li>inline-block のサンプル 3</li><!--
--><li>inline-block のサンプル 4</li><!--
--></ul>

こんなふうに改行部分をコメントアウトすれば、改行コードを隠すことができます。
解決法 1-1 のように可読性は落ちることはないです。

解決法 1-3: 改行部分を変える

こちらもよくある解決法。

<ul
><li>inline-block のサンプル 1</li
><li>inline-block のサンプル 2</li
><li>inline-block のサンプル 3</li
><li>inline-block のサンプル 4</li
></ul>

このように改行位置を本来の位置からずらすことで、li間で改行をしてないことにする方法です。
こちらも解決法 1-1 のように可読性は落ちることはないです。

解決法 2: CSS 側で直す

解決法 2-1: letter-spacing で調整

inline-block を指定している要素とその親要素に以下の指定を加えるだけ。

ul{
    letter-spacing: -.40em;
}

li{
    letter-spacing: normal;
}

解決法 2-2: font-size で調整

ul{
    font-size: 0;
}

li{
    font-size: 16px;
    width: 100px;
    vertical-align: top;
    display: inline-block;
    /display: inline;
    /zoom: 1;
}

font-size をピクセルで指定しているので、IE で文字の拡大縮小ができません。
IE7 以降はページのズーム機能がついているので問題ないとは思いますが…。

最終結果

個人的には解決法 2-1 のサンプルが一番使いやすいなと思っています。
基準にした CSS と組み合わせると、以下のようになります。

ul{
    letter-spacing: -.40em;
}

li{
    letter-spacing: normal;
    width: 100px;
    vertical-align: top;
    display: inline-block;
    /display: inline;
    /zoom: 1;
}

記述はシンプルだし、横幅を変更するだけで流用できるので汎用性が高いと思います。
解決法 2-2 でもいいのですが、修正箇所が解決法2-1に比べて1箇所増えるので次点としました。
IE での文字の拡大縮小がちょっと気になりますしね。

CSS で修正したほうがスマートな方法かと思いますが、CSS をいじれない場合もあるかもしれません。
そういった場合には、HTML をちゃちゃっといじっちゃってもオッケーだと思います。そこら辺は臨機応変に。

Firefox 2 について

inline-block 系の記事では、Firefox 2 用に display: -moz-inline-box; という指定がされているものが多いですが、Firefox 2 は、2008 年末で開発とサポートを終了しており、もう対象ブラウザからはずしちゃってもいいかなーと思っています。
アップグレードできないなら他のブラウザ使ってねーと Mozilla も言ってますし(参考ページ: 次世代ブラウザ Firefox – 旧バージョンのダウンロード の下方)。

というわけで、Firefox 2 用の指定は削除してあります。
そのため、Firefox 2 で見ると崩れているかと思います(display: inline-block; に対応していないため)。

もし Firefox 2 にも対応させたい場合は、ヨモツネットさんが公開してくれているスライドを参考にしてください。
参考ページ: 書籍などに紹介されていない display : inline-block について (ヨモツネット http://www.yomotsu.net/works/081016cssnite/ )