等幅フォントが使われる要素の扱いがブラウザー間でまちまちな問題

少し前にFixing browsers’ broken monospace font handlingNice Web Type経由で読んだんだけど、「単純に初期設定が違うだけだろ……%指定すれば大丈夫じゃね?」とか高をくくってたら大間違いだった。font-size: 100%がうまく動かなかったり、pre要素はともかくcode要素辺りでの実装のずれとか、monospaceだけだとWebKitでおかしくなるバグとかも絡んできてかなりの魔窟のようだ。この記事では触れられていないけど、言語設定によって等幅フォントの初期サイズが違うこともあるので更なるカオス。

記事で最初に挙げられているコードでも良いのだけど、normalize.cssではこの問題への対処がちゃんとなされているので、細かいことは余り考えずにnormalize.css使うのが手っ取り早い。記事の最後に挙げられているコードのように、ラテン系の言語に設定されているブラウザーでの挙動(等幅フォントを1段階小さいフォント・サイズにする)に合わせる場合は、normalize.cssのコードも混ぜた上である程度ネストへも対処するように書く必要がある。

html {
  font-size: 100%;
}

pre,
code,
var,
samp,
kbd,
tt {
  font-family: monospace, serif;
  _font-family: 'courier new', monospace;
  font-size: 0.8125em;
}

pre code,
pre var,
pre samp,
pre kbd,
pre tt {
  font-size: 100%;
}

rem単位さえ使えれば……という感じだ。と、対処を書いた所でどういう問題があって、どうすれば解決でき、なぜ今まであまり表面化しなかったのかということをちょっと書く。

存在する問題

問題はだいたい以下の4つに分けることができる。

解決するための条件

現時点では以下の3つの条件が統一のために必須ということになりそう。

  1. ユーザー設定や言語設定の違いを吸収するためにfont-sizeを指定する
  2. Firefox 10とChrome 17、Safari 5のためにfont-familyプロパティーで二種類以上指定する
  3. 親要素でのfont-sizeプロパティーの値としてem単位を使わず%単位を使用する

で、上記コードのような形になるわけ。

問題が表面化しない理由

多くの場合body要素でベースとなるフォント・サイズを指定し、preを始めh1要素などあらゆる要素でそれに対する相対的な値(%em)を使うことが多い。ベースとなるフォント・サイズは慣例的に%pxを使う人が多く、かなりの確率で条件3はクリアされる。ジェネリック・ネームのみでフォント・ファミリーを指定する人はまずいないので、条件2でハマることはまずないだろう。

問題になるのは条件1で、これはフォント・サイズを指定するかどうかにかかっており、ここでハマる可能性はかなり高い。が、そもそもこのバグがうまくフォント・サイズが反映されないというバグなので、指定しない場合はこの問題は発生しているが表面化しない。


僕の場合は長らくYUI CSS Fontsを使っていたというのが、この問題に対して無知だった理由だと思う。YUI CSS Fontsを使うだけで条件1と3はクリアできるので、上記CSSコードを自分なりに書き換えて使っても良いけど、YUI CSS Fontsでも事足りる。YUI CSS Fontsはちょっとな……というのならnormalize.cssがお手軽かつ無難。