display: inline-block; による隙間を消すCSS完全版

何気にずっと頭を悩ませてた問題。display: inline;display: inline-block; で要素をインライン化したときに、改行が半角スペースになり、隙間となる問題。あれがスッキリ解消できました。

HTMLでこんな感じ↓にしてる人は必見です。

<ul><li>list item</li><li>list item</li></ul>
  
<ul><li>
  list item
</li><li>
  list item
</li></ul>
  
<ul><!--
  --><li>list item</li><!--
  --><li>list item</li><!--
--></ul>

隙間を消す方法として、多く紹介されてきた方法が3つあります。

  • 親要素に font-size: 0; を指定し、子要素のフォントサイズをpxなどの絶対単位で指定する(%やemなどの相対単位は不可)
  • 親要素の文字間隔を狭め(letter-spacingプロパティに負の値を指定)、子要素の文字間隔を戻す(letter-spacing: normal; を指定)
  • 親要素の単語間隔を狭め(word-spacingプロパティに負の値を指定)、子要素の単語間隔を戻す(word-spacing: normal; を指定)

結論から言うと、この3つ全てを利用するのですが、その前に、それぞれの指定がブラウザでどのように表示されるかまとめましたのでご覧ください。

共通するHTMLとCSSはこんな感じ↓です。

<ul>
  <li>ul &gt; li</li>
  <li>ul &gt; li</li>
</ul>
html { font-size: 100%; }
ul, li { margin: 0; padding: 0; list-style: none; }
ul { background: gray; }
li { background: silver; display: inline-block; *display: inline; *zoom: 1; }

※IE7はインラインレベル要素にのみ display: inline-block; が有効になります。ブロックレベル要素には *display: inline; *zoom: 1; を指定することで擬似的にインラインブロック化できます。このとき、*zoom: 1; によってIEの独自仕様である hasLayout が true になり、改行による隙間が発生しなくなります。

font-size: 0;

従来の方法と大きく違うところは、CSS3 の :root(ルート要素=HTMLファイルではhtml要素を指定するための擬似クラス)と rem(ルート要素のフォントサイズを 1em とした相対単位)を使用していることです。これにより、CSS3対応ブラウザでフォントサイズを相対単位に戻すことができます。

html { font-size: 100%; }
ul, li { margin: 0; padding: 0; list-style: none; }
ul { background: gray; }
:root ul { font-size: 0; }
li { background: silver; display: inline-block; font-size: 1rem; *display: inline; *zoom: 1; }
表示結果
CSS3対応の Firefox・Opera・IE9 には有効ですが、CSS3未対応の IE8、CSS3 に対応しているはずの Safari が無効です。CSS3未対応の IE7 に影響はありません。

font-size: 1px;

Safari はフォントサイズが 0 より大きい値しか適用できないようなので、font-size: 1px; を指定してみました。

html { font-size: 100%; }
ul, li { margin: 0; padding: 0; list-style: none; }
ul { background: gray; }
:root ul { font-size: 1px; }
li { background: silver; display: inline-block; font-size: 1rem; *display: inline; *zoom: 1; }
表示結果
CSS3未対応の IE8 以外には有効です。CSS3未対応の IE7 に影響はありません。

letter-spacing: -1em;

html { font-size: 100%; }
ul, li { margin: 0; padding: 0; list-style: none; }
ul { background: gray; letter-spacing: -1em; }
li { background: silver; display: inline-block; letter-spacing: normal; *display: inline; *zoom: 1; }
表示結果
Opera 以外は有効ですが、Safari は要素が重なっています。IE7 に影響はありません。

word-spacing: -1em;

html { font-size: 100%; }
ul, li { margin: 0; padding: 0; list-style: none; }
ul { background: gray; word-spacing: -1em; }
li { background: silver; display: inline-block; word-spacing: normal; *display: inline; *zoom: 1; }
表示結果
Safari 以外は有効です。IE7 に影響はありません。

display: inline-block; ではなく display: inline; を指定した場合、Safari は letter-spacing: -1em; と同様の結果になりました。

letter-spacing: -1em; & word-spacing: -1em;

html { font-size: 100%; }
ul, li { margin: 0; padding: 0; list-style: none; }
ul { background: gray; letter-spacing: -1em; word-spacing: -1em; }
li { background: silver; display: inline-block; letter-spacing: normal; word-spacing: normal; *display: inline; *zoom: 1; }
表示結果
全てのブラウザに有効ですが、Safari は要素が重なっています。IE7 に影響はありません。

display: inline-block; ではなく display: inline; を指定した場合、Safari は letter-spacing: -1em;word-spacing: -1em; という結果になりました。

まとめると、以下のような結果になりました。

ブラウザ font-size: 0; font-size: 1px; letter-spacing: -1em; word-spacing: -1em; letter-spacing: -1em; & word-spacing: -1em;
Safari 無効 有効 有効 (要素は重なる) 無効 有効 (要素は重なる)
Firefox 有効 有効 有効 (要素は重ならない) 有効 (要素は重ならない) 有効 (要素は重ならない)
Opera 有効 有効 無効 有効 (要素は重ならない) 有効 (要素は重ならない)
IE9 有効 有効 有効 (要素は重ならない) 有効 (要素は重ならない) 有効 (要素は重ならない)
IE8 無効 無効 有効 (要素は重ならない) 有効 (要素は重ならない) 有効 (要素は重ならない)
IE7 影響なし 影響なし 影響なし 影響なし 影響なし

一番やっかいなブラウザだったのは、font-size: 0; letter-spacing: -1em; word-spacing: -1em; で残念な表示結果になる Safari でした。これらの結果を踏まえた完成形がこれ↓です。

html { font-size: 100%; }
ul, li { margin: 0; padding: 0; list-style: none; }
ul { background: gray; letter-spacing: -1em; word-spacing: -1em; }
:root ul { font-size: 1px; letter-spacing: -1px; word-spacing: -1px; }
li { background: silver; display: inline-block; font-size: 1rem; letter-spacing: normal; word-spacing: normal; *display: inline; *zoom: 1; }
表示結果
全てのブラウザに有効です。IE7 にも影響はありません。

解説すると、CSS3対応ブラウザにのみ font-size: 1px; letter-spacing: -1px; word-spacing: -1px; を指定し、CSS3未対応ブラウザには letter-spacing: -1em; word-spacing: -1em; を指定。そして、子要素に font-size: 1rem; letter-spacing: normal; word-spacing: normal; を指定して元に戻します。

ポイントは、ブラウザでの最小表示サイズである 1px を font-size, letter-spacing, word-spacing に指定したことです。

※親要素の幅ピッタリに子要素を並べる場合(グリッドレイアウトなど)、Operaのズーム機能を使うとカラム落ちする場合があります。この問題を回避するには font-size: 1px; の部分を font-size: 0.1px; に変更してみてください。

これで、厄介な隙間とはおさらばです。

本来、font-size: 0; letter-spacing: -1em; word-spacing: -1em; などを指定した場合の各ブラウザでの表示結果まで、W3C などが標準化してくれれば、このようなくどい方法を指定せずに済むんですけどね。