Rails + Vue / Tailwind CSSに日本語適用のAdobe Fontsを設定

自作サービスで日本語のAdobe Fontsを利用するにあたって、Adobe Creative Cloudだと有料のせいか、Nuxt.jsで設定する記事しかなかったので備忘録として残す。
間違っている点などがあればご指摘願います🙇‍♀️

Rails 6.1.6
Ruby 3.2.2
Vue 3.2.47
Tailwind CSS 3.1.8

Tailwind CSSはyarnで入れてます。

Adobe Fontsの埋め込みコード

Adobe Fontsの概要は以下(詳しい説明は割愛します。)

欧文フォントの場合だと、@import url("https://use.typekit.net/●●●.css");のように生成されるが、東アジア用フォントの場合だと、ダイナミックサブセットが自動でセットされる為、以下のようなスクリプトが生成される。

<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>

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

Adobe Fonts | ダイナミックサブセットと Web フォント提供

以下抜粋

ダイナミックサブセットは、東アジアの Web フォントを提供することを目的として開発されました。この機能により、サイズの大きな東アジアのフォント(ほとんどの場合グリフ数 10,000 以上)を、読み込み時間に大きな影響を与えずに Web サイトで読み込むことが可能です。

ダイナミックサブセットは、ニュースフィードやコメントセクションなど、DOM(Document Object Model)へのすべての変更を検知し、フォントサブセットに追加する必要のある新しい文字をサーバーにリクエストします。このようにして、フォントを読み込むたびにフォント全体をダウンロードするのではなく、追加のグリフのみをリクエストし、ブラウザーですぐに更新できるようになりました。

欧文フォントだと、フォント数も少ないので容量は軽いが、日本語はフォント数が多いので、ダウンロードに時間がかかる。 フォント全体をダウンロードするかわりに、ブラウザで使用する文字だけを要求して、ブラウザ上でそれを更新することができるので、日本語フォント特有の問題である、表示の延滞を軽減することが出来る。

日本語のAdobe Fontsの導入手順

Adobe Fontsで生成したコードをjsファイルに転機

いくつかeslintに怒られるため/* eslint-disable */を設定。
下記はPrettierでコード整形された状態。
kitId: '●●●'は個々に割り振られるid。

adobe-font.js

/* eslint-disable */
document.addEventListener('DOMContentLoaded', () => {
  ;(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)
})

上記のadobe-font.jsファイルをapp/javascript/packs/application.jsにimport。

tailwind.config.jsに設定

今回、Kinto Sansというフォントで太さはThin/Light/Regularで作成。
設定方法は以下を参考にさせていただきました🙏

tailwindcssでfont-familyの設定
Issue #293 · tailwindlabs/discuss

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './app/views/**/*.html.slim',
    './app/helpers/**/*.rb',
    './app/javascript/**/*.js',
    './app/javascript/**/*.vue',    
  ],
  theme: {
    extend: {
      fontFamily: {
        base: ['kinto-sans']  ← Adobe Fonts / Webプロジェクト の font-familyを転記
      }
    },
  },
  plugins: [],
}

font-baseとしてタグに設定するとkinto-sansのフォントが設定される。

読み込ませたいタグにfont-baseを設定

bodyにfont-baseを設置。
Thinにしたかったので、font-weight: 100;と生成時にfont-style: normal;cssに設定するように指示があったので、Tailwind CSSfont-thinnot-italicを設定。

app/views/layouts/application.html.slim

html
  head
    省略
    = javascript_pack_tag 'application', 'data-turbolinks-track': 'reload'
  body.font-base.font-thin.not-italic ← ここ
    header.max-w-screen-lg.mx-auto
      = render 'layouts/header'
    main.mx-auto class="#{content_for?(:main) ? yield(:main) : 'max-w-screen-sm'}"
      = yield
    footer
      = render 'layouts/footer'

無事、フォントがブラウザで読み込めました🎉

kitIdにdotenvを設定

このままではkitIdがもろばれなので、.envでkitIdを管理することにしました。

dotenv導入

Rails.envを利用しているが、gem 'dotenv-rails'はjsファイルだと利用出来ないので、yarn add dotenvで導入。

% yarn add dotenv
.env

# Adobe FontのIDを追加
KIT_ID = '●●●'
% rails c
irb(main):001:0> ENV['KIT_ID']
=> "●●●"

jsファイルで使用できるように設定

config/webpack/environment.js

require('dotenv').config() ←一番上に設置
adobe-font.js

kitId: process.env.KIT_ID

問題なく、表示されました!

フォントのちらつき

ダイナミックサブセットで設定しているものの、リロードする度にWebフォントが適用される前の状態が一瞬表示されてしまいます。

Adobe Fonts | フォントイベント

いくつかの記事を参考に以下を設定すると、header部のナビ以外のちらつきは解消されました。

html { 
  visibility: hidden;
}

html.wf-active {
  visibility: visible;
}

javascriptで設定する方法もあるようですが、一旦、下記記事を参考にさせてもらい🙏 ちらつきを解消させました。
Adobe Typekitのチラつきをなくしましょう!

body {
  animation: body-fade-in 1s ease 0s 1 normal;
}

@keyframes body-fade-in {
  0% {
    opacity: 0
  }
  100% {
    opacity: 1
  }
}

ちらつき防止については他の設定方法がわかったら、ブログを更新します。
Google Fontsのように@importで生成できなかったので最初戸惑いましたが、設定できてよかった〜。