Mac/iOS Safariでバックスラッシュを円記号として表示する方法

Unicodeではバックスラッシュ*1と定義されているU+005Cだが、歴史的な背景によりMS系日本語フォントでは円記号が割り当てられているのはよく知られた話。

ところがMac/iOSに載っているヒラギノ角ゴシック等ではU+005Cはバックスラッシュとして表示されるし、キーボードの右上の円記号キーを打つとU+005CではなくU+00A5 Yen Signが入力される*2

それぞれのシステム内で閉じてれば一貫性が保たれるのだけど、Windowsで円記号を意図して入力したU+005Cが、Mac/iOSではバックスラッシュとして表示されてしまう。企業で使われるWebシステムの場合、Windows PCとiPhone/iPadってメジャーな組み合わせだし、円記号が化けるってのは日本企業ではわりと見過ごせない問題だったりする。

実はSafariではこのバックスラッシュ円記号問題への特別対応コードが入っていて、以下の2条件のいずれかを満たすとU+005Cを円記号(U+00A5)として表示してくれる。

  1. font-familyにMS系日本語フォントが先行して指定されている
  2. HTMLドキュメントの文字コードがレガシーな日本語系文字コードである

1. font-familyにMS系日本語フォントが指定されている

クライアントのMaciOSメイリオがインストールされていなくても、以下のように先行してメイリオを指定することでSafariでは5CがA5(円記号)に置換して表示される。

body {
  font-family: Meiryo, "Hiragino Kaku Gothic ProN", sans-serif;
}

See the Pen Safari converts U+005C(Backslash) to U+00A5(Yen Sign) by teppeis (@teppeis) on CodePen.

Safari (WebKit) のソース*3を見ると、

useBackslashAsYenSignForFamily()という関数で以下のフォント名がハードコードされている。

  • MS PGothic
  • MS Pゴシック
  • MS PMincho
  • MS P明朝
  • MS Gothic
  • MS ゴシック
  • MS Mincho
  • MS 明朝
  • Meiryo
  • メイリオ

これらのフォントがfont-familyで実際に有効なフォント(ここでは"Hiragino Kaku Gothic ProN")よりも先に指定されていれば円記号置換が発動する。

このissueで対応された模様(スレッドは長かったので読んでない)。

WebKitではfont-familyで日本語フォント名は通らないが、この置換処理の判定では歴史的互換性のために日本語も考慮されている。 これを利用すると、"Meiryo"を"メイリオ"にすることで、メイリオがインストールされているMacでもメイリオではなくヒラギノ角ゴシックを表示しつつ円記号も表示できる。

body {
  font-family: "メイリオ", "Hiragino Kaku Gothic ProN", sans-serif;
}

企業ユースだとMacMS Officeがインストールされることが多く、メイリオインストール率も高いのでそこそこ有効。 さらに以下のようにすれば「Mac Safariではヒラギノかつ円記号、Windowsではメイリオ」になる。

body {
  font-family: "メイリオ", "Hiragino Kaku Gothic ProN", Meiryo, sans-serif;
}

ただし、あくまでSafari限定であってMac ChromeMac Firefoxには通用しない(後述)。

2. HTMLドキュメントの文字コードがレガシーな日本語系文字コードである

ソースを追ってみると、

260行目からnonBackslashEncodingsっていうHashSetを組み立てていて、以下の文字コードであればU+005Cが円記号として表示される。

でもまあ、いまどきEUC-JPでWebサービス作るとかっていう選択肢は無さそう。

@font-face unicode-rangeを使う正攻法

上記2つの円記号置換ルールはSafari特有なので、Safari/WebView以外にブラウザが存在しないiOSには効果的だけど、Mac ChromeMac Firefoxには通用しない。

これを正攻法で修正するなら、CSS @font-faceunicode-rangeを使ってヒラギノのU+005Cだけを円記号専用Webフォントに置き換えるというテクニックになるか。

@font-face {
  font-family: "Hiragino Kaku Gothic ProN";
  src: url("path/to/yen-sign-only-font.woff");
  unicode-range: U+005C;
}
body {
  font-family: "Hiragino Kaku Gothic ProN", sans-serif;
}

ただし、まだunicode-rangeに対応してないFirefoxとかは、ヒラギノはあきらめて完全にメイリオに切り替えるしかなさそう。

*1:いまはBACKSLASHではなくREVERSE SOLIDUSが正式名称

*2:ことえりの設定で変更は可能

*3:iOS 8のUser Agentが600.1.4だったので、ここでは一応その最新のタグを参照しておく