Webフォントの使い方 (CORSのあたり)

この「がとらぼ」でも使っていますが、Webフォント。ウェブサイトを見る側の端末に入っていないフォントをウェブサイト作成者の意図どおりに表示させられるので作る側の自己満足ではあるんだけど良いです。
日本では英数字のフォントやアイコンフォントのFont Awesomeなど何気に多く使われてはいますが、日本語Webフォントは自由に再配布できるのが殆ど無いとか漢字を含むとファイルサイズが大きいというのがネックになってそれほどは普及していません。

「がとらぼ」で使っているのはGoogleが配布している日本語WebフォントのNoto Sans。そのままだとファイルサイズが巨大すぎて表示がとんでもなく遅くなるので第一水準の漢字に丸めたサブセット版。500KBくらいでかなり小さめ。これの作り方は検索するといっぱい出てきます。

で、表示のさせ方ですが、とりあえずcssを以下のようにすると表示できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@font-face {
    font-family: 'Noto Sans';
    font-style: normal;
    font-weight: normal;
    src: url('/fonts/NotoSansJapanese-DemiLight.woff') format('woff'),
    url('/fonts/NotoSansJapanese-DemiLight.eot') format('embedded-opentype');
}

body {
	font-family: 'Noto Sans', sans-serif;
}

1〜7行目でフォントの読み込み指定。2行目で「Noto Sans」という名前(任意)を宣言して5,6行目でフォントの置き場所の指定。この場合は ドキュメントルートから見て/fontsフォルダ下にフォントファイルがある。
9〜11行目がbodyでfont-familyを指定。ここで指定するフォント名は2行目のものと対応させる。sans-serifはNoto Sansが読めなかった場合のため予備指定。

「がとらぼ」のような単独サイトならこんな感じで終わり。

いくつかサイトを持っているとWebフォントを1サイトで配布して他のサイトでもそれを使いたい場合がある。管理楽だし。
仮にblue.example.comを持っていてそこにWebフォントを置きred.example.comでそのWebフォントを利用したいとなったとき。
上のcssでいえば5行目をsrc: url('http://blue.example.com/fonts/NotoSansJapanese-DemiLight.woff') format('woff'),のようにしてやれば良い。(6行目も同様に)
また、httpsとhttpの両対応ということであればURLはhttp://などと決め打ちにせずにhttp: https:のどちらも無しのスラッシュ2本からで指定します。

1
src: url('//blue.example.com/fonts/NotoSansJapanese-DemiLight.woff') format('woff')

ところで、red.example.comでは指定した筈のblue.example.comに置いてあるWebフォントは多くの場合は表示されません。

最近のブラウザにはCross-Origin Resource Sharing(CORS)の仕組みが入っていて基本的には他所のサイトのリソースを混ぜて処理しないようになっているからです。(安全の為?)
これをなんとか表示させたいということであればWebフォントが置かれているblue.example.comの側に他のホスト(ドメイン)から使って良いという許可を与えてやります。

たとえばウェブサーバがnginxの場合はこんな感じ。

1
2
3
4
5
6
7
8
9
server {
    listen 80;
    server_name blue.example.com;
    root /hoge/path;

    location ~ \.(ttf|ttc|otf|eot|woff)$ {
        add_header Access-Control-Allow-Origin *;
    }
}

6行目のttf,ttc,otf,eot,woffはWebフォントの拡張子。Webフォント以外にcssなどを足すのもアリ。この拡張子のファイルがリクエストされた場合は7行目の最後のワイルドカードで何処のサイトからでも利用OK.

当然ですがこれだとred.example.comだけでなく他所のどこからでも利用できてしまうので非常によろしくありません。cssのような比較的小さなファイルならともかくWebフォントはサイズでかいので特に嫌です。利用してよいホスト/ドメインだけに制限します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
server {
    listen 80;
    server_name blue.example.com;
    root /hoge/path;

    set $cors ";";;
    if ($http_origin ~* (red\.example\.com|.*\.example\.org)) {
        set $cors "true";
    }

    location ~ \.(ttf|ttc|otf|eot|woff)$ {
        if ($cors = "true") {
            add_header Access-Control-Allow-Origin "$http_origin";
            add_header Cache-Control "max-age=2592000, public";
        }
    }
}

7行目に許可するホスト名,ドメイン名などを列記します。(A|B|C)という書き方。上の例ではred.example.comの他にexample.orgの各ホスト。
ピリオドはエスケーブしてやる必要があるのでホスト名とドメインを繋ぐピリオドなどの前にはバックスラッシュ(半角の¥)が必要。ワイルドカードの「.*」にはバックスラッシュ不要で、ピリオド無しのアスタリスクだけだとたぶんnginx起動時に構文エラーになります。
14行目はキャッシュ期間の指定です。秒指定なので2592000は30日となります。キャッシュ期間を指定し忘れるとWebフォントが使われない場合が多々発生します。

他の方法もありますがこれが一番単純で解りやすいかと。