自分で作るのが面倒なら人様のをパクればいい。
Material Symbols and Icon
上記サイトUIを操作し、欲しいアイコンをクリックして、コードをコピーしてHTMLファイルにペーストすればアイコン表示できた。
最小確認コード
<meta charset="UTF-8"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0&icon_names=search" /> <span class="material-symbols-outlined">search</span> <span class="material-symbols-outlined"></span>
Material Symbols and Icon読解
Material Symbols and Iconの内容を読み解いてみる。
アイコンをクリックすると画面右にコードが出てくる。それを見るとフォントは以下二種類があるらしい。
| 種類 | 概要 |
|---|---|
| 可変フォント(variable font) | 塗りつぶし、太さ、ダークモード/ライトモード、画像サイズを変更できる |
| 静的フォント(static font) | 変更できない |
ただこれ、コピーしたコードの差異を見るとURLクエリの内容が違うだけだった。
以下コードのうち前者が可変、後者が静的フォントである。
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&icon_names=search" /> <style> .material-symbols-outlined { font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24 } </style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0&icon_names=search" />
ポイントはURL部分。このクエリはWeb APIと思われる。おそらくフォントのサブセットを
URL実行
ブラウザのURL欄で上記URLhttps://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0&icon_names=searchを入力して実行すると、以下CSSが返された。
@font-face { font-family: 'Material Symbols Outlined'; font-style: normal; font-weight: 400; src: url(https://fonts.gstatic.com/icon/font?kit=kJF1BvYX7BgnkSrUwT8OhrdQw4oELdPIeeII9v6oDMzByHX9rA6RzaxHMPdY43zj-jCxv3fzvRNU22ZXGJpEpjC_1v-p_4MrImHCIJIZrDCvHOejddwaz0VEq6ZymvSXyQi4&skey=b8dc2088854b122f&v=v237) format('woff2'); } .material-symbols-outlined { font-family: 'Material Symbols Outlined'; font-weight: normal; font-style: normal; font-size: 24px; line-height: 1; letter-spacing: normal; text-transform: none; display: inline-block; white-space: nowrap; word-wrap: normal; direction: ltr; -webkit-font-feature-settings: 'liga'; -webkit-font-smoothing: antialiased; }
そしてsrc属性値にある長いURLがフォント本体のファイルである。形式はwoff2らしい。どうやらWebAPIでファイルを動的生成しているようだ。ファイル容量から察するに、クリックした検索用アイコンの虫眼鏡っぽい画像だけが入ったWOFF2ファイルと思われる。
つまりこれ、アイコン一個入りのWOFF2ファイルを、欲しいアイコンの種類だけ動的生成・ダウンロードするという、パフォーマンス最悪な形式。一括ダウンロードは大本のURLクエリで調整できるようだが。
URL解析
| URL構造 | 値 |
|---|---|
| URLパス迄 | https://fonts.googleapis.com/css2 |
| クエリ | ?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&icon_names=search |
URLは以下のような構造である。
プロトコル://ドメイン/パス?クエリ鍵1=クエリ値1&クエリ鍵2=クエリ値2
以下を見ると、クエリ値の中で更に法則をもたせているようだ。おそらくGoogleが作ったWebAPI内で適切に解析しているのだろう。
| URLクエリ鍵 | URLクエリ値 |
|---|---|
family |
Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200 |
icon_names |
search |
family |
値 |
|---|---|
Material+Symbols+Outlined |
Outlinedの部分はRounded,Sharpにもできる。 |
| opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200 | @の前が鍵、後ろが値。..は範囲。 |
| 鍵 | 値 | 候補 |
|---|---|---|
opsz |
20..48 |
20,24,40,48 |
wgth |
100..700 |
100,200,300,400,500,600,700 |
FILL |
0..1 |
0,1 |
GRAD |
-50..200 |
-25,0,200 |
値の候補はMaterial Symbols and IconのUIを見て抽出したもの。なのに一部差異がある。GRADの下限値はコードで見たら-50なのにUIで見たら-25だった。謎。
大まかなパターンは判った。これを元に希望するアイコンだけを入手したり、全アイコンを入手したいのだが。
icon_namesにsearch,homeなどとすれば複数アイコン取得できると思ったのだが、ダメだった。カンマを+,半角スペース,%20に変えてもダメ。また複数のクエリicon_names=search&icon_names=homeのように表記してもダメだった。てっきりサブセット作れると思ったのだが。やり方が違うのだろうか? 情報は見つけられなかった。
情報源
上記サイトが参考になりそう。たとえばSymbolsのアウトライン版で全アイコンは以下URLで入手可能らしい。
フォントは以下でダウンロードできるようだ。materialと検索ワードを入力すると関連一式が出てくる。
ソースコードからダウンロードする方法が最新版かつ完全版だと思われる。
$ git clone https://github.com/google/material-design-icons
合字
当該フォントは合字を使っている。以下は虫眼鏡と家のアイコンを表示する。searchやhomeといった文字列に一致した場合、当該グリフを表示する仕組みらしい。
<span class="material-symbols-outlined">search</span> <span class="material-symbols-outlined">home</span>
ただ、コードポイントも割り当てらているらしく、以下でも同じ表示内容となる。
<span class="material-symbols-outlined"></span> <span class="material-symbols-outlined"></span>
両者の違いは、ブラウザ上での文字列コピー時の挙動だ。前者はsearchが、後者は(e8b6)がコピーされる。両者共バイナリ配列だが、前者はUnicodeやAsciiで定義され、該当するフォントがある。後者はUnicode私用領域の一部であり、該当するフォントがない。なので後者は未定義グリフ、しばしばトウフ(豆腐。矩形のこと)が表示される。
アイコンを表記するとき、両者のうちどちらを使うべきか?
- 合字
- 私用領域
| 方法 | 長所 | 短所 |
|---|---|---|
| 合字 | 入力しやすく視認性が高くSEO的にも有利そう? | ファイル容量が多くなる。アイコン表示せず文字列そのまま表示したい場合との区別が付けられない(テキストエディタの場合。CSSならclass属性値の有無で切替可能) |
| 私用領域 | ファイル容量が少なく済む | 入力しにくく人間可読性が低くSEO的にも不利そう? |
HTMLで表示するなら合字のほうが良さそう。でもテキストエディタで使うならsearchなどの文字列がアイコン表示されてしまうのでは?(試していないから知らないが、合字は多分そういう機能だと思っている)
フォント化するのが最適解か?
図形を表示する方法は以下四つある。
このうち対象図形の表示方法としてフォントが適切か?
判断しにくい。可変フォントは便利そうに見えるけど、ほぼ使わない画像や、大した違いがない画像データが大量にあり、容量増加や通信速度低下につながりやすい欠点がある。
パフォーマンスを考慮するなら、自分でフォントを最適化する必要がありそうだ。そもそもGoogleマテリアルの可変フォントで用意された軸では不満がある場合もある。
たとえば矢印は360度あらゆる角度で表示出来るようにして欲しいが、そうした軸がない。
おそらくフォント自体、回転軸を想定していない。せいぜい縦書きの時は90度回転するくらいだろう。仮に回転に対応していたとしても比較的新しいOTFのうち極一部のフォントだけだろう。
基本的にフォントはグリフの360度任意回転を想定していないと思う。聞いたことがないし、どうやって入力するのかも判らない。まさか一度ずつ回転角度を指定し、それにコードポイントを割り当てるというのか。あまりに非効率だ。
回転だけならCSSでもできそうだ。ならば果たしてフォント形式で回転に対応するのが最適か判らない。矢印の任意角度回転は、フォントという構造で行うことではないのかもしれない。仕様諸々をよく知らないから判らないが。
でも、可変フォントで任意に軸を作れるなら、回転軸くらい作れそうな気もする。でも、それを勉強するのも大変すぎる。それよりもSVGのtransform属性値にrotate(180,128,128)とやれば回転できたのは既に確認済みなのだから、SVGスプライトで実装したほうが簡単なのでは?
それぞれに長所と短所があるため悩ましい。ただ、一度単位で任意回転したいなら各角度に文字コードを割り当てられるのは厳しい。せいぜい東西南北とその間の八方向くらいまでだろう。
各形式を勉強し、どこまでできるかを分析して、最適な方法を探るしかない。たかがアイコンごときにそこまで労力をかけたくはないのだが。しかし天下のGoogleが作ったアイコンにまで文句をつけるなら、もう自力でやるしかない。
結局、自分で調査し、納得するまで追求するしかない。我儘な自分が悪いのだから諦めて足掻こう。どこで妥協するか。どこで挫けるか。それだけの話。