✍️

FONTPLUSの使い方をまとめてみた

2025/01/09に公開

はじめに

Webフォント配信サービスのFONTPLUSの使い方をまとめました。
※スマートライセンス・プランに絞って話をしています。

JSフレームワークでの使い方もまとめています。対象フレームワークは下記です。

  • Nuxt
  • Next.js
  • Astro
  • Remix

(JSフレームワークについては、公式での説明があまりないので他の知見があればコメントしてもらえると嬉しいです)

対象読者

  • FONTPLUSの使い方を知りたい人

FONTPLUSとは

https://fontplus.jp/home

Google Fontsのような、「ウェブフォント」を配信するサイトです。日本のサービスで、日本語向けのフォントが多いです。

2025年1月6日時点では、4つのプランがあります。

今回は「スマートライセンス・プラン」に絞って説明します。「アドバンスト・プラン」との大きな違いは、「CDN経由の配信」ではなく、「JavaScriptによるダイナミック・サブセット方式」が採用されていることです。

ダイナミック・サブセット方式とは

日本語は、ひらがなや漢字を含むため文字の種類が非常に多く、フォントデータのサイズが10MB以上になることもあります。

パソコンにインストールする際には問題にならないサイズでも、ウェブサイトを表示するたびに読み込むには大きすぎるデータ量です。

この問題を解決するのが「ダイナミック・サブセット方式」です。この方式では、実際に使用される文字だけを必要な分だけ配信するため、効率的で軽量なフォント配信が可能になります。

この方式では、初回に必要なフォントデータのみを取得するため、動的に生成された文字列にはフォントが反映されません。

例えば、ページ遷移や、JSでfetchした文字列データの表示などは再度フォントデータを取得する必要があります。

初回読み込み時にフォントセットを取得してあるので, inputはフォントが反映されていますが、他の文字列は未取得なので後から表示してもフォントが反映されません。

使い方

公式にもありますがまとめました。
https://fontplus.jp/usage/services/apply

  1. 会員登録(トライアルでも必須)
  2. マイフォントへ利用するフォントを登録
  3. webサイトへ反映

1.会員登録

ここで会員登録をします。

2.マイフォントへ利用するフォントを登録

ここでフォントをマイフォントに追加できます。

3.webサイトへ反映

2で登録したフォントは、ここで確認できます。(マイフォントはフォルダ分けもできます)

登録したいフォントフォルダを選択して、スクリプトの発行を開くと
scriptタグがあるのでこちらをwebサイトに記載します。

最後に、ここでフォントを利用するサイトのURLを登録します。(登録しないとcorsエラーでフォントを読み込めません)

FONTPLUSのJavascript API

https://fontplus.jp/usage/javascript-api/method

FONTPLUSにはJSのAPIがあります。FONTPLUSから提供されるscriptを読み込むことで利用ができます。

FONTPLUSオブジェクトを参照してメソッドを利用できます。(クライアントサイドの場合は、window.FONTPLUSという形での参照になります)

今回利用するものにしぼって、簡単に解説します。(詳細は公式ドキュメントを参照してください)

型定義

interface FONTPLUS {
  reload: (init?: boolean) => void;
  isloading: () => boolean;
}

declare let FONTPLUS: FONTPLUS;

interface Window {
  FONTPLUS: FONTPLUS;
}

declare let window: Window;

typescriptで利用する型定義ファイルです。

reload

FONTPLUS.reload(true)
FONTPLUS.reload(false)

フォントデータの読み込みを行います。

引数をtrueにすると、今まで取得したフォントデータをリセットして再度フォントデータの読み込みを行います。

isloading

const isLoading = FONTPLUS.isloading()

フォントデータを読み込み中かどうか判定します。

setInterval(() => {
    const isLoading =FONTPLUS.isloading();
}, 200);

非同期処理でもなく、ローディングが終わったら自動で実行されるなどはないので
setIntervalなどと合わせて利用するのが良いかと思います。
FONTPLUS.attachCompleteEvent(callback)を使った方がシンプルかも?)

JSフレームワークでのFONTPLUSの使い方

次に、各種jsフレームワークでのFONTPLUSの使い方をまとめます。

  • scriptの設定
  • ページ遷移時でのフォント反映

の2つについて、各種フレームワークでの対応方法をまとめています。

「ページ遷移時でのフォント反映」もまとめているのは、ダイナミック・サブセット方式の関係上、ページ遷移時にフォントを反映させる必要があります。

Nuxt

scriptの設定

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          src: "https://webfont.fontplus.jp/accessor/script/fontplus.js?xxxxxxxx&aa=1&ab=2",
        },
      ],
    },
  },
});

Nuxtの場合、nuxt.config.tsscriptを設定できます。

ページ遷移時でのフォント反映

layouts/default.vue
<script setup lang="ts">
const route = useRoute();

watch(
  () => route.fullPath,
  () => {
    FONTPLUS.reload(false);
  }
);

onMounted(() => {
  FONTPLUS.reload(true);
});
</script>

ページ遷移を監視して、reloadを実行しています。初回に限ってはwatchだとフォントを反映させられないので、 onMountedで実行しています。
watchimmediate: trueを渡すと即時実行できますが、DOMの更新前に実行されてしまうのでフォントを読み込めません。詳細はこちら

SPA, SSRどちらにも対応しています。

Next.js

scriptの設定

layout.tsx
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ja">
      <head>
        <Script
          src="https://webfont.fontplus.jp/accessor/script/fontplus.js?xxxxxxxx&aa=1&ab=2"
          strategy="beforeInteractive"
        />
      </head>

      <body>
        {children}
      </body>
    </html>
  );
}

head内に、Next.jsが提供しているScriptを追加します。strategyは、ページ遷移時に読み込む関係でbeforeInteractiveにして、ページ表示前にあらかじめ読み込む用にしています。

もし、ページ遷移が無い場合は以下のようにstartegyafterInteractiveに指定して、onLoadを利用する方がシンプルかと思います。

FontScript.tsx
"use client";

import Script from "next/script";

export const FontScript = () => {
  return (
    <Script
      src="https://webfont.fontplus.jp/accessor/script/fontplus.js?xxxxxxxx&aa=1&ab=2"
      strategy="afterInteractive"
      onLoad={() => {
        if (FONTPLUS) {
          FONTPLUS.reload(false);
        }
      }}
    />
  );
};

onLoadを利用する場合は、"use client"とクライアント側での処理にする必要があります。
このようにcomponentに切り分けて、Layouthead内に追加しています。

ページ遷移時でのフォント反映

FontLoader
"use client";

import { usePathname } from "next/navigation";
import { useEffect } from "react";

export const FontLoader = () => {
  const pathname = usePathname();

  useEffect(() => {
    if (window.FONTPLUS) {
      window.FONTPLUS.reload(false);
    }
  }, [pathname]);
  return null;
};

ページ遷移を監視して、reloadを実行しています。

Astro

scriptの設定

Layout.astro
<!doctype html>
<html lang="ja">
  <head>
    <script is:inline src="https://webfont.fontplus.jp/accessor/script/fontplus.js?xxxxxxx&aa=1&ab=2"></script>
  </head>
  <body>
    <slot />
  </body>
</html>

ラッパーを作成して、head内に配置するのが楽だと思います。

is:inlineをつけないと、Astroの最適化処理に混ざって機能しなくなってしまいます。

https://docs.astro.build/ja/reference/directives-reference/#isinline

ページ遷移時でのフォント反映

AstroはSSGなので、reloadを実行する必要がありません。
ただし、ビュートランジションを適応している場合は、対応が必要です。

https://docs.astro.build/ja/guides/view-transitions/

Layout.astro
<script>
    const loadFont = () => {
        if (window.FONTPLUS) {
            window.FONTPLUS.reload(false);
        }
    };
    
    document.addEventListener('astro:after-swap', loadFont);
</script>

astro:after-swap(旧ページが新ページに置き換わった直後に発生するイベント)を監視してreloadを実行しています。

Remix

Remixは自信ないです。良いやり方をご存知でしたら教えてください!

scriptの設定

root.tsx
export default function App() {
  useEffect(() => {
    const script = document.createElement("script");
    script.src =
      "https://webfont.fontplus.jp/accessor/script/fontplus.js?xxxxxxxx&aa=1&ab=2";
    document.body.appendChild(script);

    script.onload = () => {
      if (window.FONTPLUS) {
        window.FONTPLUS.reload(false);
      }
    };

    return () => {
      document.body.removeChild(script);
    };
  }, []);

  return <Outlet />;
}

Remixの場合、scriptheadに配置するとhydrationエラーになってしまうので、クライアント側で追加するようにしています。(SPAとして運用する場合はheadに配置して大丈夫です)

ページ遷移時でのフォント反映

root.tsx
const { pathname } = useLocation();

useEffect(() => {
    if (window.FONTPLUS) {
      window.FONTPLUS.reload(false);
    }
}, [pathname]);

ページ遷移を監視して、reloadを実行しています。App内に記述するのが良いと思います。

その他

ウェブフォントのアンチエイリアス

ウェブフォントを使用すると、デザインよりもテキストが太く見えることがあります。

  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

上記のスタイルを適用することで、これを解消できます。

これは、アンチエイリアス(文字や画像のギザギザを滑らかにする技術)の設定がOSごとに異なるためです。

https://qiita.com/white_raichi/items/3901f8a243e51cb22262

フォント読み込み中のチラつき対応

回線速度が遅いとフォントの読み込みまで時間がかかってしまいます。


(このように回線が遅いと、数秒後にフォントが反映される)

テキストのチラつきが気になる場合は、以下のような対応をすると良いかと思います。

  • ページ全体にアニメーションを入れる
  • FONTPLUSのローディングを監視する

ページ全体にアニメーションを入れる

回線速度が遅いとあまり効果はないと思いますが、フェードインのようなアニメーションを追加すると
ちょうどテキストのチラつきを隠してくれるかと思います。

https://vier-kt.com/demo/post-323/#google_vignette

FONTPLUSの読み込みを監視する

ここと同じ内容です。FONTPLUSのjavascript apiを利用して、読み込み中かどうかを監視します。

setInterval(() => {
    const isLoading =FONTPLUS.isloading();
}, 200);

isloadingは、setIntervalなどと合わせて利用するのが良いかと思います。
FONTPLUS.attachCompleteEvent(callback)を使った方がシンプルかも?)

isLoadingtrueの間は表示を差し替えたりすれば、テキストのチラつき無く表示できると思います。

動的な文字列の対応

ダイナミック・サブセット方式の関係上、フォントを読み込んだ後にテキストを動的に生成すると、フォントが適応されない場合があります。


(inputタグに入力したテキストを表示させているが、フォントが適応されないテキストがある)

これに対応するには2つやり方があります。

  1. reloadを再度実行する
  2. あらかじめ必要なフォントデータを読み込む

1.reloadを再度実行する

ページ遷移時の対応と同じですが、reloadを再度実行させれば解決します。

2.事前に必要なフォントデータを読み込む

ダミーとして非表示のテキストを配置しておくことで、動的なテキストを生成する前にフォントデータを読み込んでおくことができます。(初回読み込み時に非表示のテキストを読み込む)

<div style="display:none">ダミー文字0123456HOGEhoge</div>

https://fontplus.jp/faq/4101

まとめ

複数のjsフレームワークで試してみましたが、それぞれ設定の仕方が若干異なっていて意外と大変でした。
今回は設定までにしましたが、PV数も抑える方法なども考えたいと思いました。

FONTPLUS側でダウンロード状況の変更もできるみたいですが、上手くいかなかったのでこちらも再度試したいと思いました。
https://fontplus.jp/usage/services/change-on-screen

(FONTPLUSなどに詳しい方いらっしゃればコメントor記事を書いてくださると嬉しいです)

ASTRSK

Discussion