ウェブに掲載されているソースコードなどは、通例、等幅フォントが用いられています。ところが残念な事に、等幅フォントが指定されていながら、全体として桁が揃っていないことが、技術系サービスの大手でも珍しくなかったりします。
少しでもクールな書体にしたい気持ちは分かるのですが、そのために等幅としての機能的性質を損ねてしまうのは、デメリットの方が大きいように感じられます。
原因
太字やイタリック体の装飾
シンタックスハイライトで闇雲に装飾すると、MS ゴシック
などのフォントでずれます。そもそも MS ゴシック
は Bold や Italic の字形データを持っていません。自動生成の太字は幅広、ビットマップ表示でのイタリック体は劣悪、泣きたくなります。
日本語を含むソースコードなど、こうしたフォントになる可能性が高い部分では、太字やイタリック体の装飾を施さないのが無難かもしれません。
欧文等幅フォントと和文等幅フォントの混在
メトリクスの異なるフォントを font-family
に羅列して混ぜると、全角と半角が噛み合いません。別々の基準の等幅と等幅の掛け合わせが、結果として等幅にならないのは、少し考えれば分かると思います。
半角と全角が揃っているように見えるページでも、画面の拡大(ズーム)などで文字の大きさを変えると、サイズによってマチマチで安定しません。
加えて、Unicode の影響で、日本語では全角として用いられてきた記号類が欧文フォント側にも含まれて、意図せず欧文フォントとなるケースが常態化しています。これは font-family
では制御不能な現象で、textarea
要素の中でさえ発生しがちな問題です。
対策
ブラウザ設定の monospace を使う
他のフォントと混ぜずに、総称フォントファミリ monospace
からブラウザの設定を経由して解決される仕組みに委ねましょう。
ブラウザの既定のフォントがダサいと言われようと、閲覧者にとっては、いつもの馴染みのフォント。少なくともそれ未満にはなりません。
ブラウザの設定を好みのフォントに変更している人にとっては言わずもがな、好みのテイストと異なる上に不揃いというダブルパンチは、かなりのストレスです。
font-family: monospace, monospace;
だけで、通常は十分なはずです。
lang 属性を使う
コードブロックに日本語を含めていなくても、日本語ページでは和文等幅フォントになってしまう、という悩みには lang
属性が有効です。
ブラウザの monospace
に紐付くフォントは、lang
属性毎に異なるフォントを設定できるので、内容相応の lang
属性であれば、適切に表示されるでしょう。
言語毎のフォント設定は、Internet Explorer / Microsoft Edge でも [コントロール パネル] – [インターネット オプション] – [全般] – [デザイン] – [フォント] から、Firefox では [オプション] – [言語と概観] – [フォントと配色] – [詳細設定] から。Google Chrome では拡張機能に追いやられていますが [設定] – [デザイン] – [フォントをカスタマイズ] – [フォントの詳細設定] で確認できます。lang="en"
がラテン (Latin) での設定になるのがポイントですね。
lang
属性を使うのはトリッキーに感じられるかも知れませんが、シンプルながら強力で安定しています。
更に対策
更に対策すると、他のウェブサイトでも、上記の対策済みの状態に近付けて閲覧することが出来ます。
ユーザースタイルシートでブラウザ設定を優先
ブラウザネイティブのユーザースタイルシート機能を使うか、アドオンや拡張機能を使うかは、好み次第かもしれません。
pre, div > code:only-child, .blob-code-inner, textarea[cols] {
font-family: monospace, monospace !important;
}
- 1つ目は、通常の
pre
要素以下。 - 2つ目は、コードブロックを
div
に入れるシンタックスハイライト向け。 - 3つ目は、GitHub 向け。
- 4つ目は、桁数指定でのテキストエリア向け。
あまり厳密ではないのですが、カバー率は高いと思います。
ユーザースクリプトで lang 属性を付与
Greasemonkey や Tampermonkey などで仕込みましょう。(現在の Firefox Quantum では Greasemonkey は上手く動いてくれませんでした)
// ==UserScript==
// @name Japanese monospace helper
// @namespace https://number-shot.net/
// @version 1.0
// @description Japanese monospace helper
// @include *
// @grant none
// ==/UserScript==
(function() {
'use strict';
if (/^(en|ja)($|-)/.test(document.documentElement.lang || window.navigator.language)) {
var r = /[\u3000-\u30ff\u4e00-\u9fff\uff00-\uff90]/;
var list = document.querySelectorAll('pre, div > code:only-child, .blob-wrapper > .highlight');
var lang = Array.prototype.some.call(list, e => r.test(e.textContent)) ? 'ja' : 'en';
Array.prototype.forEach.call(list, e => {
e.lang || e.querySelector('[lang]') || (e.lang = lang)
});
}
})();
コードブロックっぽい部分に日本語が含まれているかを、大雑把に判断しています。
半年くらい使っていますが、上手く行かなかったのは、某掲示板風のアスキーアートを pre
要素に入れて MS Pゴシック
が指定された時だけでした。(´・ω・`)
終わりに
Unicode と等幅の相性は、正直かなり悪いと思います。日本語だと East Asian Width の曖昧文字の問題など、リモートホストが期待する文字幅と端末で描画される文字幅が異なることに、悩まされていると思います。
そうした中で厳選された至極のフォント設定がある方には、この方法はイチオシの対処法です。お試しあれ!
コメント