GODRICH
#cssアニメーション#ボタン#ローディング#トランジション#スクロール#ダッシュボード#実用ui#デザイントレンド

キネティックタイポグラフィをコードで分解してみた

キネティックタイポグラフィとは、見出しの文字サイズが画面幅に合わせて変わり、単語が順番に浮かび上がり、数字がオドメーターのように上がっていくデザイン手法のことです。最近のランディングページはどれもファーストビューがこれなので、実際にコードを分解して9つのパーツに切り分けてみました。

まずは9つの部品をそのままつないだ一枚のランディングページを、上から下までスクロールしてみてください。見出しが単語ごとに浮き上がる様子、カードの数字が実際の値まで駆け上がる様子、いちばん下のワードマークを光が一度だけ斜めに横切る様子が見どころです。

ページを新しいタブで開く

下の格子にある9つは、上の画面から切り出した同じ部品です。並び順は、訪問者が実際のランディングページをたどる流れ(最初に目が止まる場所、機能をざっと見る場所、価格を確かめる場所、信頼できるか判断する場所、行動を後押しされる場所、最後にたどり着くフッター)のとおりにしてあります。文字ではなく濃い背景とグローで空気を作る側はダークSaaSのリニアなデザインシステムが担い、同じ画面を柔らかい塊へ変えるとクレイモーフィズムのLPキットになります。

自動再生 · タイルを押すとその項目へ · すべて1つのzip

01ヒーロー

キネティックタイポグラフィとは何が動くのか

見出しの3つの単語が、隠れた枠の中から順番に下から上へ現れます。

ビューポートを埋める見出し
新しいタブで開く

01 · ビューポートを埋める見出し — 計測 累積面積 12.381% · 動いたフレーム 17/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

clamp() 가변폭단어 단위 staggeroverflow: hidden 마스크

画面幅に合わせて変わる

文字サイズ自体もclamp()で画面幅に合わせて自動的に大きくも小さくもなるため、狭い画面でもはみ出しません。

<section class="flex flex-col items-center gap-6 py-24 text-center">
  <p class="text-xs font-bold uppercase tracking-[0.2em] text-accent">
    KINETIC TYPE
  </p>
  <h1 class="font-display text-6xl font-extrabold leading-[1.02]
             sm:text-7xl md:text-8xl">
    思考のスピードで<br>つくる。
  </h1>
  <button class="rounded-pill bg-ink px-8 py-4 text-base font-bold text-cream">
    今すぐ始める
  </button>
</section>

02ナビゲーション

勝手に縮んで戻るワードマーク

ナビ左側のワードマークが、放っておいても勝手に縮んだり戻ったりを繰り返します。

巨大ワードマークナビ
新しいタブで開く

02 · 巨大ワードマークナビ — 計測 累積面積 1.86% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

transform-origin: left centerletter-spacing 보간sticky 헤더

スクロールとは無関係

実際のスクロールと連動しているわけではなく、スクロールで縮む一般的なstickyヘッダーの見た目をループのデモで先に見せているだけで、変わるのは大きさだけ、字間は動きません。

<header class="sticky top-0 z-20 px-6 pt-6">
  <nav class="mx-auto flex max-w-5xl items-center justify-between
              rounded-pill bg-ink px-6 py-3 shadow-bento">
    <span class="font-display text-xl font-extrabold text-cream">MOTIF</span>
    <div class="hidden items-center gap-8 sm:flex">
      <span class="text-sm font-semibold text-cream/70">概要</span>
      <span class="text-sm font-semibold text-cream/70">機能</span>
      <span class="text-sm font-semibold text-cream/70">料金</span>
    </div>
    <button class="rounded-pill bg-accent px-5 py-2 text-sm font-bold text-cream">
      始める
    </button>
  </nav>
</header>

03カードグリッド

0から実際の値まで

カードの中の数字が0から実際の値(248)まで、桁をそろえたまま駆け上がります。

巨大数字カード
新しいタブで開く

03 · 巨大数字カード — 計測 累積面積 9.127% · 動いたフレーム 16/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

@property 숫자 보간counter-resettabular-nums

読み上げ用の隠しテキスト

counter()で描いた数字はスクリーンリーダーが読み上げられないため、上がりきった最終値(「プロジェクト248件」)を見た目だけ隠したテキストとして別に用意してあります。

<section class="py-14">
  <h2 class="mb-8 font-display text-3xl font-extrabold">数字で見る実績</h2>
  <div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
    <div class="rounded-tile bg-ink p-8 text-center shadow-bento">
      <p class="font-display text-6xl font-extrabold tabular-nums text-cream">
        248
      </p>
      <p class="mt-2 text-sm font-semibold text-cream/70">プロジェクト</p>
    </div>
    <div class="rounded-tile bg-ink p-8 text-center shadow-bento">
      <p class="font-display text-6xl font-extrabold tabular-nums text-cream">
        99.9%
      </p>
      <p class="mt-2 text-sm font-semibold text-cream/70">稼働率</p>
    </div>
  </div>
</section>

04機能一覧

3行が順に寄って戻る

3行のリストが上から順に右へわずかに寄っては戻り、下の下線も同じ拍子で伸びては消えます。

1行1機能・大きな番号
新しいタブで開く

04 · 1行1機能・大きな番号 — 計測 累積面積 7.512% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

grid 번호 정렬호버 translateX@keyframes underline-grow

番号は装飾でしかない

左側の大きな番号はコードエディターの行番号のような装飾で、実際の機能名は常に文字として隣にあるため番号だけでは意味が途切れません。

<ul class="divide-y divide-line rounded-tile bg-white shadow-bento">
  <li class="grid grid-cols-[auto_1fr] items-baseline gap-6 p-6">
    <span class="font-display text-3xl font-extrabold text-accent
                 tabular-nums">01</span>
    <span class="text-lg font-bold">リアルタイム共同編集</span>
  </li>
  <li class="grid grid-cols-[auto_1fr] items-baseline gap-6 p-6">
    <span class="font-display text-3xl font-extrabold text-accent
                 tabular-nums">02</span>
    <span class="text-lg font-bold">自動デプロイ</span>
  </li>
</ul>

05料金

月額と年額のあいだ

月額(19,000円)と年額(190,000円)の間を、価格の数字が自動で行ったり来たりします。

価格数字が主役
新しいタブで開く

05 · 価格数字が主役 — 計測 累積面積 4.107% · 動いたフレーム 18/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

숫자 롤 애니메이션@keyframes price-rolltabular-nums

本物の切り替えを足す

ボタンを押して切り替わるトグルではなく最初から最後まで勝手に動くデモで、実際のサービスに組み込むときはこの場所に本物の月額・年額切り替えボタンを足せば済みます。

<div class="flex flex-col items-end gap-4 sm:flex-row">
  <div class="flex-1 rounded-tile bg-white/60 p-8
              shadow-[0_6px_12px_rgba(23,20,26,.08)]">
    <p class="font-bold">無料</p>
    <p class="mt-2 font-display text-4xl font-extrabold tabular-nums">¥0</p>
  </div>
  <div class="relative flex-[1.1] rounded-tile bg-ink p-8 pt-10
              shadow-bento-hover">
    <span class="absolute -top-3 left-8 rounded-pill bg-accent px-3 py-1
                 text-xs font-bold text-cream">おすすめ</span>
    <p class="font-bold text-cream/70">プロプラン</p>
    <p class="mt-2 font-display text-5xl font-extrabold tabular-nums
              text-cream">
      ¥19,000<span class="text-lg font-semibold text-cream/60"> / 月</span>
    </p>
  </div>
</div>

06お客様の声

カーテンのように一気に

超大型の引用文が左から右へ、カーテンを開くように一気に現れます。

超大型引用文
新しいタブで開く

06 · 超大型引用文 — 計測 累積面積 7.105% · 動いたフレーム 20/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

clip-path: inset()단어 단위 stagger@keyframes wipe-reveal

01とは違うワイプ方向

01のヒーローが使う上下方向のマスクとは違い、こちらはclip-pathで左右方向にワイプする手法です。

<section class="py-14">
  <h2 class="mb-8 font-display text-3xl font-extrabold">お客様の声</h2>
  <figure class="rounded-tile bg-white p-10 text-center shadow-bento">
    <p class="font-display text-3xl font-extrabold leading-snug sm:text-4xl">
      「スピードがチームの文化を変えた」
    </p>
    <figcaption class="mt-4 text-sm text-ink/60">パク・ジフン・グロースリード</figcaption>
  </figure>
</section>

07CTA帯

継ぎ目なく流れる文言

横幅いっぱいの帯の中を、CTA文言が継ぎ目なく流れ続けます。

マーキーCTA
新しいタブで開く

07 · マーキーCTA — 計測 累積面積 8.303% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

translateX(-50%) 루프margin 간격(gap 금지)hover 일시정지

gapではなくmargin-right

文言をまるごと2組つなげてトラック1本にし、ちょうど半分(-50%)だけ動かすのがコツで、間隔はgapではなく項目ごとのmargin-rightで取らないと、一周するたびに数ピクセル飛んでしまいます。

<div class="relative overflow-hidden rounded-tile bg-accent py-8">
  <div class="flex w-max animate-marquee">
    <span class="mr-12 flex-shrink-0 whitespace-nowrap font-display
                 text-5xl font-extrabold text-cream">今すぐ始める —</span>
    <span class="mr-12 flex-shrink-0 whitespace-nowrap font-display
                 text-5xl font-extrabold text-cream">今すぐ始める —</span>
    <span class="mr-12 flex-shrink-0 whitespace-nowrap font-display
                 text-5xl font-extrabold text-cream" aria-hidden="true">今すぐ始める —</span>
  </div>
</div>

08フッター

ワードマークを横切る光

フッター最下部の巨大なワードマークの上を、光の帯が斜めに一度だけ通り過ぎます。

巨大ワードマークフッター
新しいタブで開く

08 · 巨大ワードマークフッター — 計測 累積面積 4.284% · 動いたフレーム 8/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

background-clip: textgradient sweepclamp() 초대형 폰트

大半は静止している

background-clip: textで文字の形の中だけにグラデーションを閉じ込め、光が通り過ぎたあとはループの大半を静止したまま過ごします。

<footer class="py-14">
  <div class="grid grid-cols-2 gap-4 sm:grid-cols-3">
    <div class="rounded-tile bg-ink/[.04] p-5">
      <p class="mb-2 text-xs font-bold uppercase tracking-wide text-ink/50">
        製品
      </p>
      <p class="text-sm font-semibold">機能</p>
    </div>
    <div class="rounded-tile bg-ink/[.04] p-5">
      <p class="mb-2 text-xs font-bold uppercase tracking-wide text-ink/50">
        会社
      </p>
      <p class="text-sm font-semibold">利用規約</p>
    </div>
  </div>
  <p class="mt-10 text-center font-display text-7xl font-extrabold
            text-ink/[.06] sm:text-8xl">MOTIF</p>
</footer>

09ボタン・入力

中央から伸びる下線

リンク型ボタンの下線が、ホバーすると中央から左右へ伸びてからまた縮みます。

下線アニメーションリンクボタン
新しいタブで開く

09 · 下線アニメーションリンクボタン — 計測 累積面積 2.883% · 動いたフレーム 22/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

transform: scaleXtransform-origin: centerfocus-visible 링

フォーカスは別枠で示す

マウスでホバーしなくてもキーボードでフォーカスを移すと別枠の:focus-visibleが必ず現れるため、下線アニメーションひとつだけに頼らずに今どこにいるかがわかります。

<div class="flex flex-col items-center gap-6 rounded-tile bg-ink p-10
            sm:flex-row sm:justify-center">
  <button class="relative border-0 bg-transparent font-display text-2xl
                 font-extrabold text-cream after:absolute after:-bottom-1
                 after:left-0 after:right-0 after:h-[2px] after:bg-accent">
    詳しく見る
  </button>
  <label class="relative w-full max-w-xs rounded-[12px] bg-cream/5">
    <input class="w-full rounded-[12px] border border-cream/30 bg-transparent
                  px-4 py-3 text-sm text-cream outline-none" type="email"
           placeholder="メールアドレス" readonly>
  </label>
</div>

tailwind.config カスタム

参照するのは設定ひとつ

ここまでの9つの部品と一枚のランディングページは、すべてこの設定ひとつだけを参照しています。

書き換えれば一度にそろう

色・書体・角丸・影の値をここで書き換えると、画面全体の色調が一度にそろって変わります。

theme: {
  extend: {
    colors: {
      cream: "#fff7e6",
      ink: "#17141a",
      accent: "#2f6df6",
      line: "rgba(23,20,26,.08)",
    },
    fontFamily: {
      display: ["'Space Grotesk'", "system-ui", "sans-serif"],
      body: ["'Inter'", "system-ui", "sans-serif"],
    },
    borderRadius: { tile: "20px", pill: "999px" },
    boxShadow: {
      bento: "0 14px 24px rgba(23,20,26,.10)",
      "bento-hover": "0 20px 32px rgba(23,20,26,.16)",
    },
    spacing: { gutter: "14px" },
  },
},

バイブコーディング プロンプト

数行渡すだけで伝わる

上の設定をプロジェクトに貼り付けたら、Claude CodeやCursorには次のような数行を渡すだけで十分伝わります。省略していない指示文の全文はzipのprompt.mdにそのまま入っています。

背景はcream(#fff7e6)ひとつだけ。カードは真っ白ではなくink(#17141a)の上にcreamの文字を置く。
見出しと大きな数字にはfont-display(Space Grotesk)、本文にはfont-body(Inter)を使い、両者を混ぜない。
強調が必要な場所(ボタン・おすすめバッジ・CTA帯)にだけaccent(#2f6df6)を使い、二つ目の強調色は入れない。
角丸はrounded-tile・rounded-pillの二値だけを使う。

実際に得た結果

この指示をそのままpage/index.htmlに渡して得た結果を、1280px幅のビューポートでページ全体キャプチャとして残しました。

結果

どこで壊れるか — 落とし穴

theme() が静かに無視される

このスタイルでいちばん多い落とし穴は、背景色や文字色を<style>タグの中でtheme()関数を使って直接指定することです。Tailwind Play CDNはbg-creamのようなコンパイル済みのユーティリティクラスの中のtheme()は正しく処理しますが、<style>タグの中に直書きしたbackground: theme('colors.cream')は静かに無視され、ブラウザ既定値(透明な背景・黒い文字)へ戻ってしまいます。このプロジェクトも最初は<body>の背景・文字色とh2の書体まで全部<style>タグのtheme()で指定していましたが、実際にレンダリングして確かめると、背景は透明(computed backgroundがrgba(0,0,0,0))、文字はink色ではなくただの黒、見出しの書体も反映されていない、という状態でした。<body class="bg-cream text-ink font-body">のようにコンパイルされるユーティリティクラスへ書き換え、h2一つひとつにfont-displayクラスを直接付けてはじめて正しく直りました。文字を細かく割って動かすこの方法がまるごと封じられる場所がメールの受信箱で、アニメーションを使えない環境でどう印象を残すかはメルマガのデザインテンプレートが見せてくれます。二つ目の落とし穴は02のワードマークです。見た目はスクロールに連動しているようですが、実際はスクロール監視なしのループ再生なので、字間まで一緒に縮むと期待してコードをそのまま流用すると、大きさしか変わらず戸惑うかもしれません。9つの部品と一枚のランディングページのソースを丸ごと収めたzipには鍵がかかっていて、そのパスワードはy9my63zgで、本文の下にあるボタンから受け取れます。

数字がちらつく理由

三つ目の落とし穴は03・05の数字アニメーションです。@property --numでsyntax: '<integer>'を宣言しないと、ブラウザは0.5や1.7のような小数の途中値まで補間してしまい、数字がちらつきながら進みます。整数型を宣言してはじめて、桁がきれいにひとつずつ上がります。

アクセシビリティ

動きを減らすと最終状態だけ

9つのデモはすべてMDNのprefers-reduced-motionのページが定めるメディアクエリで包んであり、動作を減らす設定を有効にした方には単語が浮き上がったり数字が駆け上がったりする代わりに、静止した最終状態だけが見えます。

数字とマーキーの扱い

03・05の数字はcounter()で描いているためスクリーンリーダーが読み上げられず、実際の値を見た目だけ隠したテキストとして常に添えてあります。

フォーカスは常に見える

07のマーキーで複製した半分はaria-hiddenにして同じ文言を二度読み上げないようにし、09は下線アニメーションとは別に:focus-visibleの枠を常に有効にしてあるため、動きを止めた環境でもフォーカスの位置がわかります。

ほかの kinetic typography examples やトレンドが気になる方はデザイントレンドのカテゴリーにまとめてあり、このサイトを運営しているのが誰かはサイト紹介ページでご確認いただけます。

FAQ

キネティックタイポグラフィ 作り方で使ったMOTIFやKINETICの名前をそのまま使ってもいいですか?

はい、問題ありません。この記事の部品は特定の実在ブランドをコピーしたものではなく、ピンタレストでよく見かけるキネティックタイポグラフィの雰囲気を参考に考えた架空の名前(MOTIF)とラベル(KINETIC)ですので、ご自身のサービス名に置き換えていただいて構いません。

Space GroteskやInter以外の書体に変えてもいいですか?

可能です。tailwind.config.jsのfontFamily.displayとfontFamily.bodyの二つの値を変えるだけで、9つの部品すべてに新しい書体が一度に反映されます。ただし、太く目立つ見出し・大きな数字(display)と落ち着いた本文(body)という役割分担そのものは残しておくことをおすすめします。

Tailwindを使わず素のCSSだけでも使えますか?

使えます。zipに入っているtokens.cssがtailwind.config.jsと同じ値を--color-creamや--radius-tileのようなCSS変数として書き出しているので、Tailwindのクラスの代わりにvar(--radius-tile)と直接参照すれば、色や角丸をそのまま合わせられます。動く文字がかえって邪魔になる製品紹介なら、信頼感のあるSaaS向けLPキットの落ち着いた並びのほうが合います。

解凍パスワードを入力してください

パスワードはこの記事の本文の中にあります。読み進めると出てきます。