要素に適用されているフォントを取得する

#はじめに
サイトを見ていて気になるフォントを見かけたら、みなさんどうやってフォント名を調べていますか？ソースを表示して調べるか、開発ツールのインスペクターなどを使う人が多いのではないでしょうか？

今回は、JavaScriptで要素に適用されているフォントの取得をやってみます。自分で作成したページでやってもほとんど意味はないので、アドオンやブックマークレットで使います。アルゴリズム的に正しいのか自信はありません。

動作確認は、Windows PCで行っています。MacやLinuxでも動けばいいなという気持ちで作っていますが、使える環境がないので動作確認できていません。
#要素からfont-familyを取得する
フォントを調べたい要素に対して、getComputedStyle()を使って font-familyの値を取得します。font-familyに設定されているフォントがすべて出てきます。これを見るだけでも、どのフォントが表示に使われているか大体見当はつくのですが、今回は使われているフォントの判別をプログラムで行ってみます。

```Javascript
    // elは、フォントを調べたい要素    
    var cssv = getComputedStyle(el,'').fontFamily;
```
font-familyには、複数フォントが指定されている場合が多いので、split()を使ってフォント名を１つずつ取り出し、取り出したフォントの有効・無効・英語フォント・和文フォントの判別を行います。先頭から調べて行き最初に見つかった有効なフォントが要素に適用されているフォントということになります。有効なフォントを見つけたら、それが日本語に対しても有効か調べます。

#フォントの有効・無効を判別する
font-familyには、Windowsのみに入っているフォント(Segoe UIとか)、Macのみに入っているフォント(ヒラギノ系)などいろいろなフォントが設定可能です。font-familyに設定されているフォントが、自分の使っているOSに入っていなければ、そのフォントは使われずに別のフォントがテキスト表示に使われます。以下は、使用可能なフォントを判別する手順です。

１．コンテンツの内容にしたがって大きさが変わるボックスを作成しておきます（positionにabsoluteやfixedを設定）。
２．このボックスのfont-familyに有効とわかっているフォント（今回はmonospaceを使用）を設定、文字列を表示してボックスの幅を記録します。
３．調べたいフォント＋monospace　をボックスのfont-familyに設定してボックスの幅を測ります。幅が2.で測ったものと異なるならブラウザで使える有効なフォントということになります。
また、フォントが無効な場合は２番目のmonospaceが使われるので、ボックスサイズは2.で測ったものと同じになります。ただし、有効なフォントでもmonospaceと同じサイズになる場合もあるので、monospace以外の有効なフォントを使って再検査します。再検査の結果も2.と同じなら無効なフォントと判断します。

上で書きましたが、フォントの判別には、monospaceともうひとつ別の有効なフォントを使って行います。別のフォントとは、同じ文字を表示したとき表示した文字の幅が、monospaceと異なるものなら何でもOKです。

#ソース全文
上記のフォントの判別部分をオブジェクトにまとめて、動作確認できるようにhtmlに入れたソースです。
ピンクのボックスに設定されているfont-familyのすべてのフォントをその中に表示して、ボックスの下に表示に使われている英語フォント、日本語フォントを表示します。

```html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>フォント名取得テスト</title>
<style>
body{
    font-size: 16px;
}

#box1{
    margin: 50px auto 3px auto;
    padding: 8px;
    width: 360px;
    text-align: center;
    background: #faa;
    /* いろいろなフォントを使ってテストしてみてください */
    font-family: "Segoe UI", Georgia, Arial, 'ヒラギノ角ゴシック Pro', "Hiragino Kaku Gothic Pro", メイリオ, Meiryo, sans-serif;
}

#result{
    text-align: center;
}
</style>
</head>
<body>
<div id="box1"></div>
<div id="result"></div>

<script>
var oFont = {
    // 判別用ボックス
    el: null,

    // 判別用文字列（英文フォント用、和文フォント用）
    cstr: ["afgiqwi059 MWA/|", "あいぅぇぉ和文フォント"],

    // 判別用フォント（initメソッドで gfontから選ぶ）
    cfont: [],

    // 判別用フォントの候補
    gfont: [
            ["sans-serif","serif","cursive","fantasy","Arial"],
            ["MS PMincho","MS PGothic","Osaka","TakaoPGothic","IPAX0208PGothic","IPAPMincho"]
           ],

    // 初期化
    init: function(){
        var i,j, w;

        // 判別に使用するボックスを作る
        this.el = document.createElement("div");
        document.body.appendChild(this.el);
        this.el.style.position = "fixed";
        this.el.style.top = "-1000px";
        this.el.style.fontSize = "33px";
        this.el.style.backgroundColor = "#aff";

        // 判別に使用するフォントを選ぶ
        for(i = 0; i < 2; i++){
            this.el.style.fontFamily = "monospace";
            // 文字列を入れてboxの幅を取得
            this.el.textContent = this.cstr[i];
            w = this.el.offsetWidth;
            // box幅がmonospaceと異なるfontを探す
            for(j = 0; j < this.gfont[i].length; j++){
                this.el.style.fontFamily = this.gfont[i][j];
                if(w != this.el.offsetWidth){
                    this.cfont[i] = this.gfont[i][j];
                    break;
                }
            }
        }
    },

    // font-familyの値から要素に適用されているフォントを見つける
    // 戻り値　オブジェクト（プロパティeに英文フォント、プロパティjに和文フォント）
    ffcheck: function(ff){
        var i, s, r, rr=0, font={e:"", j:""};

        s = ff.replace(/\"|\'/g,"");                // "'を削除
        ar = s.split(",");
        for(i = 0; i < ar.length; i++){
            s = ar[i].trim();
            r = oFont.check(s);
            if(r > rr){
                if(r == 1)
                    font.e = s;
                else
                    font.j = s;
                rr = r;
            }
            if(rr > 1)
                break;
        }
        return font;
    },

    // fntが有効なフォントか調べる
    check: function(fnt){
        var i, w, f = 0;

        for(i = 0; i < 2; i++, f++){
            this.el.innerHTML = this.cstr[i];
            this.el.style.fontFamily = "monospace";
            w = this.el.offsetWidth;
            this.el.style.fontFamily = fnt+",monospace";
            if(this.el.offsetWidth == w){
                this.el.style.fontFamily = fnt+","+this.cfont[i];
                if(this.el.offsetWidth != w)
                    break;
            }
        }
        return f;
    },
};

var el = document.getElementById("box1");
var cssv = getComputedStyle(el,'').fontFamily;
el.innerHTML = "このボックスの font-familyには<br><br>"+cssv+"<br><br>が設定されています";

oFont.init();
var font = oFont.ffcheck(cssv);
el = document.getElementById("result");
el.textContent = "適用フォント　英："+font.e+"、　和："+font.j;

</script>
</body>
</html>
```

#実行結果
Windows PCでの実行結果は↓のようになりました。MacやLinuxでは、違う結果になっているはずです。うまく動いていたらの話ですが。
当方、MacもLinuxも使える環境にないので、Windows以外での動作確認ができません。もし正しく動かないようなら、判別用フォント候補にmonospaceとは表示サイズが違っているだろうと思われるフォントをいくつか追加してみてください。動かない場合の原因はここが一番確率が高いです。
別のフォントで試したい場合は、スタイルシートの＃box1のfont-familyを変更してください。
![Screenshot-2018-6-13 フォント名取得テスト.png](https://qiita-image-store.s3.amazonaws.com/0/263237/0448d265-039b-50b5-b163-c1d91f852404.png)

#フォント判別オブジェクトの解説
oFontにフォントを判別するためのプロパティとメソッドをまとめました。
##使い方
・oFont.init()で初期化（フォント判別の準備をする）
・oFont.ffcheck()に調べたい要素のfont-familyの値を引数にして呼び出す。英語フォント、和文フォントが入っているオブジェクトが返ってくるので、それを表示する。
##プロパティ
>el:
判別で使用するボックスを示しています。
>
cstr:
フォントの判別で使う英語文字列と日本語文字列です。
>
gfont:
monospaceとはサイズが異なると思われる、英文に有効なフォント、日本語に有効なフォントの候補です。
>
cfont:
init()で見つけた、判別に使う英語フォント・和文フォントを入れます。

##メソッド
>init()
判別に使用するボックスを見えない位置に作成。
判別に使用するmonospaceとは異なるフォントを見つける。
>
ffcheck()
font-familyの値から要素に適用されているフォントを見つける。
戻り値　オブジェクト（プロパティeに英文フォント、プロパティjに和文フォント）。
>
check()
フォントが無効か有効かを調べる
戻り値　0:無効なフォント、1:英語フォント、2:和文フォント


#ブックマークレットに組み込んだ使用例
下の画像は、この記事に載せたフォント判別オブジェクトの元になったものを組み込んであるブックマークレットで、Qiita様のガイドラインページのフォントを調べたときのものです。

![WS000026.JPG](https://qiita-image-store.s3.amazonaws.com/0/263237/e53192ae-2477-81fd-23af-9a48ccd0bfd4.jpeg)

↑のブックマークレット
[CSSをチョメチョメするブックマークレット](https://cssroller.com/)
[要素に適用されているフォント名を調べる](http://fanblogs.jp/cssroller/archive/17/0)

#WindowsでHelveticaが使える ?
上の画像では、見出しに適用されているフォントとして、「Helvetica」と「メイリオ」が表示されています。私が使っているのはWindows PCなので「メイリオ」はいいとして「Helvetica」で？？となりました。「Helvetica」はMacには入っているけどWindowsには入っていないはずです。
プログラムにバグがあるのかな？とも思ったのですが、実際にfont-familyに「Helvetica」を設定してみると有効なようです。
また、次のように ``` font-family: Helvetica, Impact;``` を設定して英文を表示してみました。「Helvetica」がOSに入っていなければ、「Impact」で表示されるはずですが、「Impact」の特徴的な太字では表示されません。
何かソフトを入れたときにいっしょに「Helvetica」がインストールされたのかと思いfontが入っているフォルダを調べてみましたが、見つかりませんでした。
この「Helvetica」で表示された文字を他のフォントに変えてみるとぴったりのフォントがありました。「Arial」です。
「Arial」は「Helvetica」と似せて作られたということで同じに見えても不思議ではないのですが、まったくちがいが見つかりません。本当に「Helvetica」なら少しはちがう部分があるはずです。
そこで、開発ツールのインスペクタで調べてみると、要素に適用されているフォントは「Arial」となっています。

これって、font-familyに「Helvetica」が設定されていると、Windows PCでは、OSかブラウザが「Arial」に置き換えて表示しているということなのでしょうか？？私のPCだけで起る現象なのか、他のWindows PCでもそうなるのか気になります。

#おわりに
長文にお付き合いいただきありがとうございます。記事を読んでいただいた方に何か少しでもプラスになるようなものがあればうれしいです。

#MacやLinuxのフォントを参考にさせていただいたサイト
[フォントカタログ・標準の日本語フォント](http://rinrin.saiin.net/~aor/fonts/fonts)