Web / アイコンフォントの CSS 設定 2015

アルファベットが沢山あるイメージ

WEB フォントやアイコンフォントを CSS に設定するとき、多くの場合に次のようなコードが設定されています。 例えば WEB フォントの使い方を解説するサイトや、アイコンフォントのジェネレータがこのようなコードを使います。

@font-face
{
    font-family: 'sample-font';
    src: url('font.eot');
    src: url('font.eot?#iefix') format('embedded-opentype'),
         url('font.woff') format('woff'),
         url('font.ttf')  format('truetype'),
         url('font.svg#sample-font') format('svg');
}

このコードは多くのシチュエーションに対応するのですが、極端に古いブラウザのための設定や、重複する設定が含まれています。 そこで、執筆時時点で実用的なコードを提案します。

私が提案するのは次のようなフォントの設定です。IE 8+, Android, iOS, FF, Safari, Opera などに対応します。 さらに "エミュレーションされた IE にも対応" できます。

src: url('font.eot');
src: url('font.woff') format('woff'),
     url('font.ttf') format('truetype');

厳密には IE6+ に対応するようですが検証していません。 また svg フォントを完全に削除したことで、著しく古い OS (iOS) に対応することができません。いずれにしても問題は大きくないでしょう。

?#iefix の仕組み

src: url('font.eot?#iefix') format('embedded-opentype'),
     …;

?#iefix コードについて解説します。 このコードが IE でどのように動作するのかを理解しておくことは、ここで提案する CSS を理解するために重要です。

IE8 以前のブラウザでは、src プロパティに複数の url を設定することができず、単一の url だけをパースして読み込みます。 また、format をパースすることができません。(パースとは、ブラウザがコード解析し読み込める単位に分解することです。)

IE8 以前のブラウザがパースする対象は、url の冒頭にある ( から 末尾の ) までです。 したがって、複数の url が存在するとき、フォントの url は url(~) format(~), ~ url(); のようになります。 当然、そのような url は存在しないので、フォントの読み込みに失敗し 404 エラーが発生します。

ところが、? がパースの途中に存在するとき、? 以降のテキストは、読み込まれる url のパラメータとして扱われます。 リソースの読み込み時には url のパラメータは考慮されないので、? 以前の文字列が url として扱われます。

url 冒頭の ( から ? が現れるまでの文字列は読み込みたいフォントの url を正しく示すので、 IE8 以前のブラウザでも、正常にフォントを読み込むことができます。

#iefix は、人間に向けたコードであって、? が古い IE のために記述されていることを示すだけです。 ブラウザの処理を制御するコードではありません。

単独で指定する src はエミュレータ向けの設定である

src プロパティ には複数の url を設定することができますが、IE8 以前のブラウザ (IE) は 1 つの url しかパースすることができません。 ?#iefix ハックを使えば IE8 以前のブラウザも複数の url の設定を処理できるようになりますが、このハックにもまだ問題が残ります。

IE の開発者ツールは、古い IE の機能を再現する "エミュレーション" 機能を持っています。 この機能を使ってエミュレーションされた古い IE では、?#iefix ハックが機能しません。 そして、src プロパティに設定された 1 つの url しかパースすることができません。

この問題は、IE9 以降の IE で、IE8 以前の IE をエミュレーションするときに確認することができます。 具体的には、IE9 を使って IE8 をエミュレートするときや、IE11 によって IE8 をエミュレートするときに確認することができます。

エミュレーションせずに IE8 を直接使う場合には、この問題は発生しません。 したがって、エミュレーションを考慮しなければ、Web・アイコンフォントの指定は次のコードのようになります。

src: url('font.eot?#iefix') format('embedded-opentype'),
     url('font.woff') format('woff'),
     url('font.ttf') format('truetype');

しかしながら、エミュレーションを考慮しつつ、IE8 以前の IE を考慮するコードも大きな差がありません。 つまり、ここでお勧めしているコードです。

src: url('font.eot');
src: url('font.woff') format('woff'),
     url('font.ttf') format('truetype');

Reference