AppRouterとTailwindCSSを使っているNextプロジェクトでAdobeFontsを使ってみた
概要
AdobeFontsでは契約しているライセンスが有効な間、Webサービス向けにフォントを使用することができます
「Webプロジェクトに追加」を選ぶとJSスクリプトが表示されます
これをどうにかしてNext13のプロジェクトで使いたいのですがパッと思いつくdangerouslySetInnerHTML
はあまりにダーティーなので、コンポーネント化してみました
何故かまだあまり情報が出回っていなかったのでメモしておきます
env
- typescript: "5.2.2"
- next: "13.5.2"
- react: "18.2.0"
- tailwindcss: "3.3.3"
TypekitLoaderコンポーネントの作成
原文で渡されるスクリプトを示します。CSSテキストを直接読みにいっているわけではなく、kitIdをクエリとしたjsを呼んで環境に適用するものであることがわかります。
<script>
(function(d) {
var config = {
kitId: 'xxxxxx',
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>
これと同等のものをコンポーネントとして実装します。
このスクリプトはクライアントサイドで呼び出してあげる必要があるので、use client
をつけてクライアントコンポーネントとして作成しました。
できるだけ元のスクリプトを踏襲して書きましたが、読みにくいのでアレンジしたほうがいいかもです。
"use client"
import { useEffect } from 'react';
const TypekitLoader: React.FC = () => {
useEffect(() => {
(function (d: Document) {
const config = {
kitId: `${process.env.NEXT_PUBLIC_ADOBE_FONTS_KIT_ID}`,
scriptTimeout: 3000,
async: true,
};
const h = d.documentElement;
const t = setTimeout(() => {
h.className = h.className.replace(/\bwf-loading\b/g, '') + ' wf-inactive';
}, config.scriptTimeout);
const tk = d.createElement('script');
h.className += 'wf-loading';
tk.src = `https://use.typekit.net/${config.kitId}.js`;
tk.async = true;
tk.onload = function () {
clearTimeout(t);
try {
(window as any).Typekit.load(config);
} catch (e) {}
};
tk.onerror = function () {
clearTimeout(t);
};
const s = d.getElementsByTagName('script')[0];
s.parentNode!.insertBefore(tk, s);
})(document);
}, []);
return null;
};
export default TypekitLoader;
エラー処理とかはいい感じに変更しましょう。
useEffect
を使ってロード時に呼び出しています。
複数のフォントを使う場合も似たような方針で書けるかと思います。
環境変数の指定
kitIdは追跡されるべきではないので、.env.local
に書きます。クライアント側で使うのでNEXT_PUBLIC
としています
NEXT_PUBLIC_ADOBE_FONTS_KIT_ID=xxxxxx
CSSの設定
読み込んだCSSをTailwindで使用できるようにします。
AdobeFontsでスクリプトを作成した時に表示されるCSS用の名称を渡せばTailwindで有効になります。
import type { Config } from 'tailwindcss'
const config: Config = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
+ fontFamily: {
+ tsukuaoldmin: ['fot-tsukuaoldmin-pr6n', 'sans-serif'],
+ },
},
plugins: [],
}
export default config
スクリプトのロードが終わっていないとデフォルトのフォントがロードされて画面が崩れる可能性があるので、globals.css
にwf-active
クラスを持たない場合は表示しないようひと手間加えました。
@tailwind base;
@tailwind components;
@tailwind utilities;
html {
visibility: hidden;
}
html.wf-active {
visibility: visible;
}
layout.tsxから呼び出す
最上位のlayout.tsx
から先ほど作成したコンポーネントを実行します。
これで{children}
の要素では全てfont-ont-tsukuaoldmin
を指定できるようになるはずです。
import '@/styles/globals.css'
import TypekitLoader from '@/app/TypekitLoader'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ja">
<TypekitLoader />
<body>{children}</body>
</html>
)
}
使ってみた
<p className=" text-white font-tsukuaoldmin">FOT-筑紫Aオールド明朝 Pr6N</p>
こんな感じです。本当に綺麗なフォントですよね、筑紫オールド
Discussion