2011-04-04

display: inline-block を使う(修正版)

週末に @nagomu さんと @terkel さんが YUI grids.css や stacklayout.css で指定している word-spacingletter-spacing の値はなんでこの値なんだろうね、という話をされていて、おもしろそうだったので、数字の原因を探ったり、いろいろなブラウザーでチェックしてました。

いろいろなブラウザーでチェックをしている時に、以前書いた記事 display:inline-block; を使うで紹介していた CSS ではブラウザーごとに微妙な誤差があったので、修正版を書いてみました。

以前書いていたコード

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

.child {
  letter-spacing: normal;
  vertical-align: top;
  display: inline-block;
  /display: inline;
  /zoom: 1;
  width: 100px; /* 任意の値 */
}
  • 古いバージョン古いバージョン古いバージョン
  • 古いバージョン
  • 古いバージョン古いバージョン
  • 古いバージョン

こちらのコードでもうまくいくことが多いのですが、Windows 版の Opera で<li>の右側に空白が発生してしまいました(バージョン、ビルドが同じ Mac 版の Opera では問題なし)。

YUI と StackLayout を参考にしてみたものの版

次に YUI grids.css、stacklayout.css を参考に word-spacing を追加してみました。

word-spacing の値については、冒頭で紹介した @nagomu さんの記事で stacklayout.css と同じ(-0.65em)でいいんじゃないかという結論が出ていました。

なお、YUI grids.css の値だと、WebKit 系ブラウザーで以下の問題が出ました。

.parent {
  letter-spacing: -1em;
  word-spacing: -1em;
  width: 600px; /* 任意の値 */
}

.child {
  letter-spacing: normal;
  word-spacing: normal;
  display: inline-block;
  vertical-align: top;
  /display: inline;
  /zoom: 1;
  width: 100px; /* 任意の値 */
}
  • 試してみたバージョン試してみたバージョン試してみたバージョン
  • 試してみたバージョン
  • 試してみたバージョン試してみたバージョン
  • 試してみたバージョン

いろいろ試してみてた結果、上記の CSS を適用すれば Windows 版 Opera でもうまくいきましたが、WebKit 系のブラウザーで子要素が前にめり込むようになってしまいました。

WebKit 系向けの指定部分の letter-spacing: -1em; を削除するとめり込まなくなりますが、当然 WebKit 系の空白が埋められず。

ちょっとチカラ技な気がするけどうまくいった版

なんとかできないかといろいろ試した結果、以下の指定でなんとかなりました。
1つ上のコードとの違いは、letter-spacing: -1em; を削除したことと display: table; を追加したこと。

.parent {
  word-spacing: -1em;
  display: table;
  width: 600px; /* 任意の値 */
}

.child {
  word-spacing: normal;
  display: inline-block;
  vertical-align: top;
  /display: inline;
  /zoom: 1;
  width: 100px; /* 任意の値 */
}
  • チカラ技バージョンチカラ技バージョンチカラ技バージョン
  • チカラ技バージョン
  • チカラ技バージョンチカラ技バージョン
  • チカラ技バージョン

word-spacing の値については、細かい検証は行なってません。
数字が単純で、ちゃんと効いているようなのでひとまず。

動作は以下のブラウザーでチェック。

Windows: IE 6〜9, Firefox 4, Opera 11.01, Safari 5.0.4, Chrome 10.0
Mac: Firefox 4, Opera 11.01, Safari 5.0.4, Chrome 10.0

うまく効いていない環境などありましたらご連絡いただければと思います。

※ 2011年4月21日@terkel さんからのおかしくなるパターンと解決方法を教えていただきました。

IE 8と IE 9で発生。
子要素(ここでは .child )に :hover を指定すると、親要素に :hover した際に最初の子要素が :hover 状態になってしまう。
文章では分かりにくいので、サンプルを見てみてください。

.parent {
  word-spacing: -1em;
  display: table;
  width: 600px; /* 任意の値 */
}

.child {
  word-spacing: normal;
  display: inline-block;
  vertical-align: top;
  /display: inline;
  /zoom: 1;
  width: 100px; /* 任意の値 */
}

.child:hover {
  cursor: pointer;
  background: red;
}
  • :hover を指定しておかしくなるパターン
  • :hover を指定しておかしくなるパターン。:hover を指定しておかしくなるパターン
  • :hover を指定しておかしくなるパターン
  • :hover を指定しておかしくなるパターン。:hover を指定しておかしくなるパターン

このサンプルで、子要素がないエリアでも :hover が反応してしまっているのが分かるかと思います。

そして、これの解決方法は、親要素に display:block\9; を指定すること。
「\9」の部分は IE 8と9用のハックです。

.parent {
  word-spacing: -1em;
  display: table;
  display: block\9; /* IE 8, 9用の指定 */
  width: 600px; /* 任意の値 */
}

.child {
  word-spacing: normal;
  display: inline-block;
  vertical-align: top;
  /display: inline;
  /zoom: 1;
  width: 100px; /* 任意の値 */
}

.child:hover {
  cursor: pointer;
  background: red;
}
  • :hover を指定しておかしくなるパターン解決版
  • :hover を指定しておかしくなるパターン解決版。:hover を指定しておかしくなるパターン解決版
  • :hover を指定しておかしくなるパターン解決版
  • :hover を指定しておかしくなるパターン解決版。:hover を指定しておかしくなるパターン解決版

問題の発見と解決方法を教えてくださった @terkel さん、ありがとうございます。

その他、うまく効いていない環境、パターンなどがありましたら教えてください。