本文へスキップ

技術

Satori で OG画像を作るときに詰まった3つ

Next.js の next/og は、JSX を書くと画像にしてくれます。CSS が使えるように見えるので油断しますが、描画しているのはブラウザではなく Satori です。3つ、実際に詰まりました。

1. filter: blur() は効かない

背景にぼかした光を置こうとして、単色の円に filter: blur() を当てました。ぼけません。硬い円板がそのまま出ます。

代わりに、光を地そのものに焼き込みます。2色を混ぜた不透明な色を作って、radial-gradient として地に置く形です。

// ratio は from 側の割合
function mix(from: string, to: string, ratio: number): string

ここで大事なのは「透明を経由しない」ことです。次の失敗がそれです。

2. 光を別の要素に置くと、箱の縁で直線に切れる

radial-gradient を持った要素を絶対配置で重ねる、という素直なやり方も試しました。Satori では絶対配置の箱が版面で切られます。 光の途中に、まっすぐな切れ目が入ります。

地の色そのものをグラデーションにすれば、切られる箱がありません。透明な重ねをやめる、というのが結論でした。

ブラウザで同じ JSX を表示すると正しくぼけるので、実装中は気づけません。生成した画像を必ず開いて見ることが唯一の検出方法でした。

3. フォントに渡し忘れた文字だけ、字形が変わる

Satori の標準フォントは日本語を持ちません。必要な文字だけを Google Fonts から取ってきて渡す形にしています。取得する URL に、描く文字列をそのまま入れます。

https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@700&text=<描く文字すべて>

問題は、渡し忘れた文字だけが Satori の既定フォントに落ちることです。エラーにはなりません。同じ一行の中でウェイトも字形も食い違った画像が、黙って出ます。

対策は仕組みのほうに入れました。カードを描く関数が、描画する文字列を1式にまとめてからフォントを取りに行きます。カードを増やしても、その関数を通るかぎり渡し忘れようがありません。

  • 文字を足したら、フォントに渡す文字列にも足す —— ではなく
  • 描く文字列とフォントに渡す文字列を、同じ1つの式にする

ついでに踏んだこと

カードそのものの話ではありませんが、同じ時期にもう1つ壊しました。プロダクトのページの layoutopenGraph を書いたところ、親の共有カードが引き継がれなくなりog:image が消えました。

そちらは別に書いています —— X は og: ではなく twitter: を読む

Notes 一覧へ戻る