eureka

NuxtでAdobe Fontsを利用する(日本語対応)

4

やっとできた・・・!

Adobe FontsはTypekitを利用しているのですが、欧文フォントを使用するだけであればlinkタグで埋め込むことができたり、web-fontloaderなどのライブラリを使用して導入することができます。

ところが和文フォント(東アジアの言語)を使用しようとするとscriptタグでの埋め込みを指定されてしまいます。

<script>
  (function(d) {
    var config = {
      kitId: '######',
      scriptTimeout: 3000,
      async: true
    },
    h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
  })(document);
</script>

そのページで使われている文字だけを動的にサブセット化する(ダイナミックサブセット)ためにスクリプトが用意されているんですね。
和文フォントは本当に重いのでいちいち全部読み込んでいたら確かに大変です。

今回はこの読み込みコードから自前の関数を用意してフォントをロードする方法となります。

AdobeFontsからプロジェクトIDを取得する

まずはAdobeFontsのタグを用意します。プロジェクトIDがわかれば良いです。

赤枠の部分がプロジェクトID(kitId)になるので控えておきましょう。

Adobe FontsのプロジェクトIDを取得する

埋め込みコードをplugins配下のファイルに定義して関数を作る

続いてpluginsディレクトリの中にadobe-fonts.jsというファイルを作成して下記のように設定します。

/* eslint-disable */
export default function ({ app }, inject) {
  const adobeFonts = (d) => {
    var config = {
        kitId: 'projectId',
        scriptTimeout: 3000,
        async: true,
      },
      h = d.documentElement,
      t = setTimeout(function () {
        h.className =
          h.className.replace(/\bwf-loading\b/g, '') + ' wf-inactive'
      }, config.scriptTimeout),
      tk = d.createElement('script'),
      f = false,
      s = d.getElementsByTagName('script')[0],
      a
    h.className += ' wf-loading'
    tk.src = 'https://use.typekit.net/' + config.kitId + '.js'
    tk.async = true
    tk.onload = tk.onreadystatechange = function () {
      a = this.readyState
      if (f || (a && a != 'complete' && a != 'loaded')) return
      f = true
      clearTimeout(t)
      try {
        Typekit.load(config)
      } catch (e) {}
    }
    s.parentNode.insertBefore(tk, s)
  }

  inject('adobeFonts', adobeFonts)
}

上記のコードのkitIdに先ほど控えたプロジェクトIDを入れます。

ちなみに埋め込みコードをそのまま入れただけなので`/* eslint-disable */`で切っておかないとこんな感じでeslintにめっちゃ怒られますw許して

   3:5   error  Split initialized 'var' declarations into multiple statements  one-var
   3:5   error  Unexpected var, use let or const instead                       no-var
  22:24  error  Expected '!==' and instead saw '!='                            eqeqeq
  22:43  error  Expected '!==' and instead saw '!='                            eqeqeq
  26:9   error  'Typekit' is not defined                                       no-undef

pluginsでの使用は下記の公式サイトのページからヒントを得ています。
Google アナリティクスを使うには?

injectすることでNuxtアプリケーション全体から共通関数として呼び出すことができるようになります。
injectに関して詳しくはこちら

nuxt.config.jsに作成した関数を登録する

pluginsで作成した関数はnuxt.config.jsで設定することによって利用できるようになります。

pluginsセクションにファイルを登録しましょう。

  plugins: [
    '~/plugins/adobe-fonts',
  ],

CSSでフォント指定

フォントをロードする前にCSSでfont-familyを設定しておきましょう。
今回使用しているフォントは下記です。

/* DNP 秀英丸ゴシック Std */
font-family: dnp-shuei-mgothic-std, sans-serif;
font-style: normal;
font-weight: 400;

ベースフォントにしたかったのでbodyに追加しました。

body {
  font-family: 'dnp-shuei-mgothic-std', 游ゴシック, 'Yu Gothic', 游ゴシック体, YuGothic, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', 'Meiryo UI', メイリオ, Meiryo, sans-serif;
  font-style: normal;
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.5;
  height: 100%;
}

LayoutsからWebフォントを読み込む

ではいよいよ関数を使用してロードしましょう。

ページ全体で読み込ませたいのでLayouts/default.vueに処理を書きました。

<template>
  <div>
    <Nuxt />
  </div>
</template>

<script>
export default {
  mounted() {
    this.$adobeFonts(document)
  },
}
</script>

レンダリング後に処理を書かないと文字を読み込めないのでmounted()内に処理を書きます。

injectした関数はthis.$xxx()で呼び出すことができます。(template内で呼び出す場合はthis不要)

これでAdobeフォントがロードできるようになりました!

チラつき防止もやる

元のフォントが一瞬表示されてからAdobeフォントに切り替わるってことよくありますよね。チラつきって言うみたいです。
こちらはCSSでなんとかできますのでサクッと対応しちゃいましょう。

サイト全体でAdobe Fontsを読み込ませる予定があれば、baseのCSSとかグローバルで設定しているスタイルから設定しても良いと思います。

特定のページでしかAdobe Fontsを使わないという場合は、使用するページごとに下記のスタイルの指定をしてあげるのが良いでしょう。

html {
  visibility: hidden;
}
html.wf-active {
  visibility: visible;
}

これでチラつきもなく綺麗に表示されていることでしょう!!!やったね!

3/19 追記 読み込みはpages側から

読み込みの部分で訂正があります。(すみません)

レンダリングの順番として、pages → layoutsと呼ばれるので、Adobe Fontsの読み込みはpageごとに呼び出すのが良さそうです。

<script>
export default {
  mounted() {
    this.$adobeFonts(document)
  },
}
</script>

私の環境でチラツキが少し目立っていて、こちらを修正したら目立たなくなりました。

調子乗ってLayoutsで!とか言ってすみませんでした。。

おまけ。試したこと

Adobe Fonts(日本語)をJSフレームワークで使用する方法はググっても本当にいい記事が出てこなくて困っていました。
やっと見つけた下記の記事たちも私の環境ではうまくいかなかったので一応軌跡として載せておきます。(失敗したの私だけ??)

headでscriptタグを読み込ませる

export default {
  head: {
    script: [
      { src: 'https://use.typekit.net/<PROJECT_ID>.js' }
    ]
  },
}

Typekitを実行

<script>
export default {
  mounted() {
    Typekit.load({async: true})
  }
}
</script>

するとぴえんです。

error 'Typekit' is not defined

独り言

Adobe Fontsは有料だし、使用するケースが少なくてみんなあんまり使わないのかなぁという結論に至りました笑

あんまり記事ないよねぇ

4