シンタックスハイライターの比較

このブログにもそろそろシンタックスハイライター(syntax highlighter)を導入しようと思って調べてみたら、なんか思ってたより種類があってげっそりです。いろいろあってドキュメント見るだけではよくわからなかったのでとりあえず一通り試してみました。シンタックスハイライターライブラリをお探しの方の参考になれば嬉しいです。

続きを読む

attributesってなんだ

Gutenberg でブロックを作る際に登場する attribute とは、一言で言うとブロック内で保持される『データ』のことです。段落ブロックであれば段落内の文章、画像ブロックであれば画像のURLやリンク先URLなどをさします。

そしてブロックを開発する際に attributes オブジェクトと言うものを作る必要があります。名前からも分かる通り上述の attribute に関連するものです。これは一体なんでしょうか? この記事では attributes オブジェクトについて見ていきたいと思います。

続きを読む

React入門 参考記事まとめ

先日 Gutenberg の記事で、ブロック開発には React の知識はそれほど必要ないと言いましたが、あれは嘘です。ごめんなさい。React の知識があるほうが何倍も開発が楽になると思います。

というわけで今回は React についてのサイトや記事をまとめました。実を言うと僕も現在進行形で React を勉強中でして、その上で役に立ったと思うものをいくつか紹介していくので、これから React を学びたいと思っている方はよかったら参考にしてみてください。

公式チュートリアル

まずは何と言っても公式サイトでしょう。一番信頼できる情報源です。日本語翻訳がないのが残念ですが、Google翻訳を片手に頑張って読むだけの価値はあると思います。


Hello World – React

React のコンセプトを体系的に学べます。実際に手を動かしながらより、理論を学びたい方にオススメです。


Tutorial: Intro to React – React

こちらも公式サイトのチュートリアルですが、やりながら勉強するタイプのものです。上記のものと比べ、自分の勉強方法にあった方を選ぶといいと思います。


解説サイト

英語を見るだけで蕁麻疹が出て死ぬという方は、日本の方が書かれているサイトを見ましょう。非公式と言っても情報が劣る訳ではなく、むしろ使う側の立場で書かれているのでこちらの方がわかりやすいかもしれません。


React入門 – とほほのWWW入門

過去に HTML や CSS などでお世話になった方もいるんじゃないでしょうか? かの有名なとほほのWWW入門ですが、なんと React までカバーしていました。僕が小中学生くらいのときによくみてたサイトなので、まさかまだ健在とは思わずびっくりです。

昔と変わらず、要点がとてもわかりやすくまとまっていてすごく読みやすい内容になってます。


一人React.js Advent Calendar 2014

React を解説するためにアドベントカレンダーをお一人で埋めたというとてもクールなページです。初歩的な部分から高度な部分まで25日間に渡って幅広く扱っています。1日ごとにテーマが決まっているので興味があるところから読めるのもグッドです。


仮想DOM

React でも取り入れられている仮想DOMという技術についても紹介しましょう。React を使用する上で知らなくてはならないものではないですが、興味がある方は読むとわくわくできるでしょう。


なぜ仮想DOMという概念が俺達の魂を震えさせるのか – Qiita

少し古い記事ですが、仮想DOMの仕組みやそもそもなぜ仮想DOMなのかと言ったところがわかりやすく書かれています。仮想DOMのメリットが分かる頃には著者の方のように魂が震えていることでしょう。


おわり

おわりです。他にオススメの記事とかありましたらこっそり教えてください。こっそり追加します。

個人的な意見ですが、React と Vue.js はどちらかを理解しているともう片方の理解がスムーズに進みますね。

以前 Vue.js を勉強していた時はとても苦しんだ記憶がありますが、今回は気軽に勉強できてる気がします。コンポーネント指向やデータの流れといった共通した概念があるからでしょう。

VCCWをスマホから見れるようにする

VCCW で作成した仮想マシンは、デフォルトの設定では Virtualbox の内部ネットワークに接続されるため、VCCW を動作させているホストPCからしかアクセスできません。

VCCW を使ってテーマ作成などをしていると当然スマホからどう見えるかも確認したいところです。Chrome の開発者ツールで仮想的にスマホでの見た目を見ることもできますが、やはり限界があり、実機で見るとレイアウトが大きくずれてしまっている、なんてこともあります。

今回は、VCCW で作成した仮想マシンをホストOSと同じネットワークにブリッジ接続する方法を紹介します。これによって同ネットワーク内にある別の端末(PCやスマホ)からアクセスできるようになります。

環境

以下の環境で動作確認しています。

  • VCCW 3.18.0
  • Vagrant 2.1.2
  • Virtualbox 5.2.12

1.すでにプロビジョニングを行なっている場合

仮想マシンを停止

起動している場合は一度停止します。

$ vagrant halt

site.yml の編集

19行目にある  ip を変更します。ここには仮想マシンに設定したいIPアドレスを指定してください。IPアドレスはホストPCやスマホと同じネットワークで、まだ使われていないものにする必要があります。

今回はホストPCが 192.168.0.3/24 なので仮想マシンに 192.168.0.150 を設定します。

ip: 192.168.0.150

Vagrantfile の編集

ネットワーク設定を内部ネットワーク接続ではなくブリッジ接続に変更します。

52行目の以下の行を

  config.vm.network :private_network, ip: _conf['ip']

以下のように修正します。

  config.vm.network :public_network, ip: _conf['ip'], hostsupdater: "skip"

:private_network を :public_network に変更し、IPアドレスで直接アクセスするようにするため hostupdater を無効にしています。

仮想マシンを起動

仮想マシンを起動します。

$ vagrant up

接続するネットワークを聞かれた場合はスマホが接続しているネットワークを選択します。

WordPressのURLを変更

一度でもプロビジョニングをしていると WordPress の URL が vccw.test などになっているので、これを先ほど指定したIPアドレスに変更します。

まず仮想マシンにSSH接続します。

$ vagrant ssh

WP-CLI で変更します。URLとIPアドレスは適宜書き換えてください。

$ cd /vagrant/wordpress
$ wp search-replace vccw.test 192.168.0.150

movefile などは適宜手動で変更する必要があります。


2.まだプロビジョニングしていない場合

site.yml の作成

$ cp provision/default.yml site.yml

site.yml の編集

18, 19行目にあるhostname と ip を変更します。プロビジョニングをしている場合と同じように、IPアドレスはホストPCやスマホと同じネットワークで、まだ使われていないものにする必要があります。

hostname 192.168.0.150
ip: 192.168.0.150

サイトURLとして hostname が使用されるので、 ip と合わせて変更しています。

Vagrantfile の編集

ネットワーク設定を内部ネットワーク接続ではなくブリッジ接続に変更します。

52行目の以下の行を

  config.vm.network :private_network, ip: _conf['ip']

以下のように修正します。

  config.vm.network :public_network, ip: _conf['ip'], hostsupdater: "skip"

:private_network を :public_network に変更し、IPアドレスで直接アクセスするようにするため hostupdater を無効にしています。

仮想マシンを起動

仮想マシンを起動します。

$ vagrant up

接続するネットワークを聞かれた場合はスマホが接続しているネットワークを選択します。


スマホから確認

スマホからIPアドレスで仮想マシンにアクセスします。今回の例ではIPアドレスは 192.168.0.150 なので、Chrome のアドレスバーに192.168.0.150 と入力します。

アクセスできれば成功です!


おわり

ドメインが使えないのでいちいちIPアドレスを直打ちしなければならないのが難点ですが、それ以外のデメリットはほとんどないと思います。wordmove によるデプロイも通常通り可能です。

スマホから見れなくて困っているという方は、念のためバックアップを取ってから試してみてください。

SVGファイルをサーバ側で圧縮する

SVGファイルの実態はシンプルなXMLなので、HTMLやCSSと同じようにサーバ側での圧縮が可能です。方法としては以下の3つが考えられるでしょう。

  1. mod_deflate を使って圧縮する方法
  2. 事前に圧縮し、SVGZファイルとして配信する方法
  3. 2の方法にgzip非対応ブラウザ用のフォールバックを追加した方法

以下の動作確認は全て Apache 2.4.34 で行なっています。

mod_deflate を使って圧縮する方法

mod_deflate は HTTPリクエストの Accept-Encoding ヘッダーをもとに、ブラウザが gzip に対応している場合のみ圧縮を行います。

gzip に対応していないブラウザでも(圧縮はされないものの)、画像が表示されなくなるといったことはありません。しかし、リクエストのたびに圧縮を行うため、サーバの負担が大きくなるというデメリットがあります。

設定方法

まず、mod_deflate が有効になっていない場合は httpd.conf を修正して有効化する必要があります。

LoadModule deflate_module modules/mod_deflate.so

次に .htaccess (またはhttpd.conf)で SVGファイルが圧縮されるように AddOutputFilterByTypeディレクティブを指定します。

AddOutputFilterByType DEFLATE image/svg+xml

デモ(圧縮無し)
デモ(mod_deflate での圧縮)

SVGZファイルとして配信する方法

SVGファイルを gzip で圧縮したものを SVGZファイルと呼びます。

事前にファイルを圧縮しておくことでサーバの負担を減らすことができます。そのかわり常に gzip で圧縮したファイルを返すため、gzip に対応しないブラウザではファイルを正常に扱えず、表示できなくなります。

設定方法

まず SVGファイルを gzip コマンドで SVGZファイルに変換します。

$ gzip ebi.svg
$ mv ebi.svg.gz ebi.svgz

そして .htaccess で、SVGZファイルが gzip で圧縮されていることをクライアントに知らせるために AddEncoding ディレクティブを使用します。

AddEncoding x-gzip .svgz

デモ(SVGZ での圧縮)

SVG、SVGZ の両ファイルを用意して配信する方法

上記で紹介した方法の『gzip非対応ブラウザで表示されなくなる』というデメリットを補う方法です。あらかじめ SVGファイル、SVGZファイルの両方を用意しておき、gzip 対応ブラウザには SVGZファイルを、非対応ブラウザには SVGファイルを返します。

設定方法

SVGファイルのリクエスト時にSVGZファイルを返す処理を行うには mod_rewrite を使います。そのため、まず mod_rewrite が有効になっていない場合は httpd.conf で有効化する必要があります。

LoadModule rewrite_module modules/mod_rewrite.so

そして .htaccess で以下の設定をします。

AddEncoding x-gzip .svgz

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} \.svg$
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}z -s
RewriteRule .+ %{REQUEST_URI}z [L]

AddEncoding ディレクティブは上記の方法と同じように SVGZファイルが gzip 圧縮されていることを示しています。

次の段落のリライトルールでは、『リクエストされたファイルがSVGファイルかどうか』、『リクエストの Accept-Encoding ヘッダに gzip が含まれるか』、『対応するSVGZファイルが存在するか』を一つずつ検査し、全てに該当するリクエストの場合にのみ SVGZファイルを返すよう指定しています。

これによってサーバの負担を減らし、なおかつ gzip 非対応ブラウザでも表示できるようになります。

デモ(SVGとSVGZをリクエストによって切り替え)

おわり

.htaccess の編集や gzip コマンドでの圧縮など、手間はかかりますが、SVGファイルをサーバ側で圧縮する場合は3つめの方法が一番良いと思います。

『gzip に対応していないブラウザ』と何度か書きましたが、実際のところそんなものは今の時代使われてないでしょう。そのため2つ目の方法でも動作しないということはほぼないと思います。

重要なのはリクエストの Accept-Encoding を見て、適切なレスポンスを返すことです。ちゃんと Accept-Encoding を見ることで、仮に宗教上の理由で gzip が使えなかったり、あるいは gzip に重大な脆弱性が見つかり gzip を完全廃止する世界がやってきた場合でも、gzip を使用するかどうかの判断をユーザに委ねることができます。

どこまでクライアント側の事情に対応するかが難しいところですが、HTTP自体の仕様にAccept-Encoding がある以上はそれに準拠した動作の方が望ましいでしょう。

object-fit で画像を自由にサイジング

object-fit プロパティは <img> や <video> などによく使用されるプロパティです。width や height などを使って指定したボックス領域に、どんな感じで画像やビデオを表示するか、というのを object-fit で指定します。

どんな感じで、と言うのは具体的にはサイズ感やリサイズ方法、表示範囲を指します。object-fit プロパティの値には fillcontaincovernonescale-down のうちのいずれかを指定でき、もちろんそれぞれ意味が異なるので意図にあったものを選ぶ必要があります。

例えば、アスペクト比を無視してボックス領域全体に画像を拡大表示したいという場合であれば fill が最適です。以下に各値がどのように作用するかについてまとめました。

fill アスペクト比を無視して、領域全体を埋めるように拡大表示する。(デフォルト値)
contain アスペクト比を保ったまま、領域に収まる最大サイズで表示する。
cover アスペクト比を保ったまま、領域全体を埋める最小サイズで表示する。
none 一切リサイズせず、ボックス領域でトリミングされる。
scale-down nonecontainのうち、サイズが小さい方で表示する。

ポリフィル

ただ、残念ながらIE11では object-fit をサポートしていません。Edgeにおいても<img>以外への使用はサポートしていないようです。

そのためそれらのブラウザ上で object-fit を使用するにはポリフィルが必要となります。オススメは object-fit-images です。<img>タグのみの対応ですが、ポリフィル導入時の変更が他のものと比べかなり少なく済むのが特徴です。

<video> などに object-fit を使用したい場合は object-fit-polyfill がいいかもしれません。こちらは試していないのでなんとも言えませんが、<img><video><picture>に対応しているようです。

object-fit-images の使用方法

参考程度に object-fit-images の使用方法も記しておきます。このポリフィルの面白いところは何と言っても font-family を使って文字列を保存している点ですね。

object-fit-images を使用する場合はHTMLとCSSの修正が必要です。

まずはHTML側でスクリプトの読み込みと呼び出しを行います。

<script src="./ofi.min.js" async></script>
<script>
  window.addEventListener('load', function() {
    objectFitImages();
  });
</script>

次にCSS側で、object-fit プロパティを指定している場所に追加で font-family で object-fit を指定します。

.cover-polyfill {
  object-fit: cover;
  font-family: "object-fit: cover";
}

これで完了です。不明な点などあれば以下のデモページも参考にしてみてください。

デモ

デモページ

object-fit のデモページです。object-fit-images をポリフィルとして使用したパターンも掲載しています。

Android P のイースターエッグをエミュレータで動かす

先日 Andoid P が正式にリリースされました。いろんな機能が搭載されているようですが、新しい Android がリリースされて一番最初に気になるのがイースターエッグという方もいるのではないでしょうか? 僕もその一人です。

イースターエッグというのは、ご存知の方も多いと思いますが、開発者が遊び心で追加したソフトウェアの隠し機能のことです。Android には古くから搭載されていて、ひそかな人気があったりなかったりします(適当)。

早速確認したいところですが、僕の携帯はまだAndroid 7.0です。Android P は Pixel シリーズに順次配信されているようですが、残念ながら持ってません。仕方ないので開発用のエミュレータで確認してみましょう。以下の手順は macOS で行なっています。

エミュレータのインストール

エミュレータを動作させるには Android SDK が必要です。Android Studio は今回使わないので Command line tools only の方をダウンロードします。

ダウンロードしたら適当な場所に android_sdk というフォルダを作り、その中に展開しましょう。

↓こんな感じのフォルダ構造になると思います。

android_sdk
  └- tools

そしたらコマンドライン上で android_sdk フォルダを開き、以下のコマンドを実行します。

$ ./tools/bin/sdkmanager "emulator" "platform-tools" "platforms;android-28" "system-images;android-28;default;x86"
$ ./tools/bin/avdmanager create avd -n android-p "system-images;android-28;default;x86"

sdkmanager コマンドで必要なパッケージをインストールし、avdmanager コマンドでエミュレータの作成をしています。途中ライセンス同意の確認メッセージが出るので y で同意できます。

↓こんな感じのフォルダ構造になっていれば成功です。

android_sdk
  ├- emulator
  ├- licenses
  ├- patcher
  ├- platform-tools
  ├- platforms
  ├- system-images
  └- tools

エミュレータの起動

ここまで終われば準備終了です。以下のコマンドでエミュレータを起動します。

$ ./emulator/emulator @android-p

イースターエッグを起動

早速イースターエッグ起動です。

上の順序でタップしていき、最後のAndroidバージョンを連打すると…

なんだかサイケデリックな画面が表示されました。タップすると色がかわります。不気味ですね。そしてさらに連打すると…

ペイントソフトらしきものが起動しました(なんで?)。

放置しておくとどんどん色が薄くなるみたいですね。

はい、これだけです。

おわり

Android のイースターエッグにはなんの説明もないので謎なことが多いです。今回はおそらく Android P だから Paint の P と掛けたのでしょう。まあ深く考えたところで大きな意味はないと思います。この謎さ加減がいい味を出してますね。

今回インストールしたものを削除したい場合は、 android_sdk フォルダと ~/.android フォルダを消せば全て削除されます。

参考リンク

Gutenberg で Hello, World!

Gutenbergについて少し勉強したのでおさらいも兼ねてサンプルを作ってみたいと思います。サンプルといっても基礎中の基礎、Hello, World をただ表示させるブロックを作成します。

Gutenbergは記事をブロックの集合体として扱う、WordPressの新しいエディタです。おそらくWordPress 5.0からは現在の TinyMCE から Gutenberg に置き換わるものと思われます。とはいえそのままTinyMCEを使う続けることもできるので、無理にGutenbergに慣れる必要はありません。

環境は最新版であるWordPress4.9.8で、Gutenbergプラグイン(3.4.0)をインストールしてあります。では早速サンプルを作っていきます。

まずブロックの雛形を作る

プラグインやテーマを作るにあたってWP-CLIを使って雛形を作成する方もいると思いますが、ブロックも同じ方法で作ることができます。とても便利なので今回もWP-CLIを使っていきます。

今回はプラグインとしてブロックを作成するため、以下のコマンドでプラグインの雛形、およびその中にブロックの雛形を作ります。

$ wp scaffold plugin my-plugin
$ wp scaffold block hello-world --title="Hello,World!" --plugin=my-plugin

ついでにプラグインの有効化も一緒にやっておきます

$ wp plugin activate my-plugin

次に、作成されたプラグインのPHPファイルからブロック用PHPファイル読み込むようにする必要があるため、wp-content/plugins/my-plugin/my-plugin.php の一番最後に以下の1行を追加します。

include( plugin_dir_path( __FILE__ ) . 'blocks/hello-world.php' );

ここまで終わったらいったんGutenbergエディタでブロック追加ボタンを押してみます。うまくいっていれば以下のように、ウィジェット欄から Hello, World! ブロックが追加できるようになっているはずです。

実際にブロックを追加してみると、Hello from the editor!とうっすら書かれた黒い四角が追加されたと思います。

ブロックを修正する

今のままでもよいですがせっかくなのでメッセージをHello, World!に変更しましょう。今回のような動的な機能を持たないブロックは基本的にJavaScriptで記述します。内部的にはReactを使用していますが、よほど込み入ったことをしない限りReactに対する深い知識は必要ないと思われます。

修正するファイルは wp-content/plugins/my-plugin/blocks/hello-world/index.js です。中を見ると51行目と66行目に edit関数と save関数が定義されているのがわかると思います。

これらの関数の戻り値が実際のブロックの表示となります。edit関数はエディタ上での表示、save関数は記事を保存した後の通常の表示をそれぞれ返しています。el関数はReactのcreateElement関数と同等で、今回の場合はタグが<p>、内容が第三引数の文字列の要素を生成しています。この関数について詳しく知りたい場合はReactのドキュメントを直接みた方が良いようです。

メッセージを以下のように変更してみます。

ブロックのスタイルも修正する

エディタ上で文字が見づらいのでスタイルも修正します。修正するファイルは wp-content/plugins/my-plugin/blocks/hello-world/style.css です。

どうもGutenbergプラグインのスタイルシートで p タグの文字色が指定されているようで、そちらの設定が優先されてしまっているようです。これはちょっと修正して欲しい気もしますが今のところは !important で強引に変えときましょう。

いざ確認

新しく記事を作成してもう一度Hello, Worldブロックを追加して見ましょう。

edit関数に指定した「Hello, World! ただ今編集中」がうまく表示されています。公開して実際にどう見えるかも確認してみます。

いい感じですね。save関数に指定したメッセージが表示されています。

おわり

というわけで Hello, World! を表示するブロックの完成です!(ワーパチパチ) 言うまでもありませんが、使い道はまったくありません。今度は表示する文字をエディタ上で編集が可能な RichText コンポーネントを使ったサンプルも作りたいですね。次回、乞うご期待です。

AnyDesk を使ってみた

AnyDeskはドイツのAnyDesk社が開発したリモートデスクトップソフトウェアです。導入がとても簡単で、多くのプラットフォームに対応しており、しかも個人利用であれば無料で使用できます。

↑macOS上でAndroidの画面を画面共有(後述の通り、Androidは画面共有のみ可)している図

導入

ダウンロードはPCであれば公式サイトから、スマートフォンであれば各種アプリストアから行えます。インストールから利用開始まで10分もかかりません。アクセスする側とアクセスされる側の両方にインストールする必要があります。

インストールすると「AnyDeskアドレス」と呼ばれる9桁の数字が自動で割り当てられます。これは各PC(またはスマートフォン)を一意に識別するための識別子で、これさえあればリモートデスクトップが可能になります。裏を返せば、それだけ簡単に接続できてしまうので(ダイアログの表示で一定のセキュリティは確保されているとはいえ)、不特定多数に公開してしまわないよう気をつけたほうがいいでしょう。

接続手順

基本的にAnyDeskアドレスを相手に教えるだけでリモートデスクトップが開始できます。デフォルトの設定では以下の手順で接続を行います。(接続する側をA、接続される側をBとしています。)

  1. Bが自身のAnyDeskアドレスをAに教える
  2. AがBのAnyDeskアドレスを入力して接続
  3. Bに「接続を許可しても良いか」を確認するダイアログが表示される
  4. 3.で許可するとリモートデスクトップが開始

なんとたったこれだけです。目をつぶりながらでもできますね。IPアドレスだのネットワーク設定だのといったこざかしい複雑さは一切ありません。通信がすべて暗号化されるという点も安心です。

無人アクセス

さらに設定を追加することで上記の3番目の手順にあるダイアログの表示を無くし、B(接続される側)が無人でも接続を可能にすることができます。これはB側に常に人がいるとは限らないケースで重宝されますが、誰でも接続できる状態となりセキュリティが落ちてしまうため、パスワードの登録が必須となります。

対応プラットフォーム

対応プラットフォームは、Windows、macOS、Linux、FreeBSD、iOS、Androidといたれりつくせりなラインナップです。が、プラットフォームによって機能に差があるので注意が必要です。

現時点では、Androidは他の端末に対して画面の共有はできますが、操作は受け付けません。iOSは他の端末からの接続自体受け付けません。課金してもこれは変わらないようなので、おそらくAndroidやiOSに仕様上の壁があるのだと思われます。

いくつかのプラットフォームで試してみましたが、ファイル転送やホワイトリストでのアクセス制御など、一番機能が多いのがWindows版のようです。

おわり

今までの人生でリモートデスクトップソフトウェアというものに触れたことがなく、なんとなく複雑そうなイメージがありましたが、それが一瞬にしてくつがえるほどの簡単さにびっくりです。他のソフトもこんな感じなのかな? リモートデスクトップソフトウェア界では TeamViewer というソフトも有名のようなので、気が向いたらそちらも使ってみたいと思います。

参考リンク

font-familyプロパティにクォーテーションは必要?

CSSでフォントを指定する際に使うfont-familyプロパティ。CSSを使う人なら必ず一度は書いたことがあるであろうプロパティの一つですが、以前から僕には一つ疑問がありました。それは何かと言うと、タイトルにもありますが、値を指定する際にクォーテーションが必要かどうか? ということです。

ちなみに以下のCSSはいずれも正常に動作します。

font-family: メイリオ, Verdana;
font-family: 'メイリオ', 'Verdana';
font-family: "メイリオ", "Verdana";

ネットで軽く検索をかけてみると、「スペースを含むフォント名にはクォーテーションが必須」や「日本語を含むフォント名にはクォーテーションが必須」といった意見が見つかりますが、試しに実際に動かしてみると、どうも正常に動くようです。果たしてこれはブラウザの忖度なのか? あるいはネット上の意見が間違っているのか? というわけで少し深掘りしてみることにしました。

結論から言うと、おそらく、日本語を含む場合もスペースを含む場合もクォーテーションは必要ありません。(※ スペースが2つ以上連続で続く場合を除く)

調べてみる

こういう時はやはり規格の仕様をみるのが手っ取り早いです。CSSはW3Cが仕様を制定していて、フォントに関する仕様は CSS Fonts Modules Level 3 でまとめられているみたいです。現時点ではまだ勧告候補で最終決定盤ではないみたいですが、まあいいでしょう(適当)。

CSS Fonts Modules Level 3 の font-family の項には以下のように書かれています。

Font family names other than generic families must either be given quoted as strings, or unquoted as a sequence of one or more identifiers.

汎用ファミリー以外のフォントファミリー名は、stringsとしてクォーテーションで囲うか、あるいはひとつ以上の identifies の並びである必要があります。

!! これは重要な情報です。フォントファミリー名の指定が identifies の並びであればクォーテーションは必要ないのです。ここでいう identifies は以下のように定義されています。

In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, two hyphens, or a hyphen followed by a digit. Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item). For instance, the identifier “B&W?” may be written as “B\&W\?” or “B\26 W\3F”.

要は identifies は[a-zA-Z0-9]、ISO 10646のU+00A0以上、ハイフン(-)、アンダースコア(_)のみを含み、かつ、数字、2つのハイフン、1つのハイフンと数字では始まらないもののことを指します(わかりづら)。ここで重要なのは、日本語はU+00A0以上なので identifies に含むことができるということです。

つまり…

これまでのことを総合するとこうです。

  • identifies の並びであればクォーテーションは必要ない。
  • 日本語もidentifies に含まれる。

つまり、フォントファミリー名に日本語が含まれようと、スペースが含まれようと、全て identifies の並びとして解釈され、クォーテーションは必要ないようです。

ひとつ気がかりなのが identifies の『並び』と言う部分です。僕は並びと言うのをスペース区切りと解釈しました(英語の文章も単語をスペースで区切って並べるし…)が、それがあってるのか正直微妙です。ですがいろんな記事に目を通したところおそらく! 僕の解釈であっていると思われます。

仕様の続き

To avoid mistakes in escaping, it is recommended to quote font family names that contain white space, digits, or punctuation characters other than hyphens:

エスケープ時の間違いを防ぐために、スペース、数字、ハイフン以外の区切り文字を含む場合、クォーテーションで囲うことをオススメします。

しかし強制ではないものの、仕様ではスペースを含む場合はクォーテーションで囲うことをオススメしているので、特に理由のない限り結局はクォーテーションを使ったほうがいいのかもれません。

注意点

ちなみに絶対クォーテーションが必要なケースが2つあって、1つはフォントファミリー名が inherit や serif などのCSSで使用するキーワードと同じ場合。

もう1つは、フォントファミリー名の中で2つ以上のスペースが連続で続く場合です。と言うのも、identifies の並びで記述された値は全てのidentifies をスペースで結合した文字列に変換されるため、2つ以上のスペースは1つのスペースに変換されてしまいます。まあそんなフォント名があるかどうかわかりませんが、そういったフォントを扱う場合は指定に気をつける必要がありそうです。

参考リンク