スクロール連動UIというと、要素がフェードしたり、少し動いたりする実装を思い浮かべることが多いです。
ただ、実際のUIでは「どこまでスクロールしたか」だけでなく、どのくらいの速さでスクロールされたかによって印象が変わることもあります。
たとえば、速くスクロールしたときは少し流れるように見せて、ゆっくり止まったときは静かに落ち着かせる。
こうした表現を入れるだけで、UIにほんの少し「手触り」が生まれます。
この記事では、Scroll Velocity Animation の基本的な考え方と、JavaScriptで実装する方法を初心者向けに整理していきます。
最後には、実際に触って確認できる実験デモの考え方も紹介します。
この記事でわかること
- スクロール速度とは何か
- scrollY の差分から速度を求める考え方
- 速度に応じて UI の見た目を変える方法
- Scroll Reveal や Scroll Story とは少し違う演出の作り方
1.Scroll Velocity Animationとは?
Scroll Velocity Animation は、スクロール位置そのものではなく、スクロールの速さを使って見た目を変えるUI表現です。
よくあるスクロール演出は、次のように「位置」を基準にしています。
- 画面に入ったらフェードインする
- 一定位置まで来たら固定する
- セクションごとに内容を切り替える
一方で Scroll Velocity Animation は、次のように「速度」を基準にします。
- 速くスクロールしたときだけ少し流す
- スクロールが止まりそうになると元に戻す
- 一時的にぼかしや移動量を強める
つまり、スクロールの結果ではなく、スクロール中の勢いを使うUIです。
2.なぜスクロール速度を使うのか
理由はシンプルで、動きに少しだけ人間らしい反応を加えられるからです。
スクロール量だけで制御すると、見た目は正確でも少し機械的になりやすいです。
そこに速度の情報を足すと、動きに「慣性っぽさ」や「勢い」が出ます。
たとえば次のような場面で相性が良いです。
- カード一覧の軽い追従演出
- ヒーロー画像の流れ感
- テキストや背景の微妙なズレ
- スクロール中だけ少しブラーを入れる表現
派手すぎる必要はなく、ほんの少しだけ変化を足すくらいがちょうどよいです。
3.基本の考え方
スクロール速度は、ざっくり言うと次のように求められます。
現在のスクロール位置 – ひとつ前のスクロール位置
たとえば、
- 前フレームの scrollY が 100
- 今の scrollY が 112
なら、差分は 12 です。
この差分が大きいほど「速くスクロールした」と考えられます。
逆に、
- 前フレームが 300
- 今が 302
なら差分は 2 なので、ゆっくり動いたことになります。
この差分をそのまま使ってもいいですが、実際には少し強すぎたりガタついたりするので、値をなめらかに補間して使うのが基本です。
4.実装の全体像
今回の流れはかなりシンプルです。
- 現在のスクロール位置を取得する
- 前回との差分を求める
- その値を目標速度として持つ
- 実際に使う速度は easing 的になめらかに追従させる
- transform や blur に反映する
この考え方なら、Scroll Trigger や Scroll Reveal よりも小さな構成で作れます。
HTML
まずは動かす要素を用意します。
今回は、中央に1枚のカードがあり、そのカードがスクロール速度に応じて少し上下し、わずかに傾く構成にします。
<section class="hero">
<div class="velocity-card" id="velocityCard">
<p class="label">Scroll Velocity</p>
<h1>Move with speed</h1>
<p class="desc">
The card reacts to how fast you scroll, not just how far.
</p>
</div>
</section>
<section class="spacer"></section>
<section class="spacer"></section>
<section class="spacer"></section>上の spacer は、スクロールできる余白を確保するためのものです。
実験として確認するときは、ある程度縦の長さがある方がわかりやすいです。
CSS
見た目はできるだけシンプルにして、速度の変化が分かりやすいようにします。
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: sans-serif;
background: #0f1115;
color: #ffffff;
}
.hero {
min-height: 100vh;
display: grid;
place-items: center;
padding: 24px;
}
.velocity-card {
width: min(560px, 92vw);
padding: 32px;
border-radius: 24px;
background: linear-gradient(180deg, #1c2230 0%, #141922 100%);
border: 1px solid rgba(255, 255, 255, 0.08);
box-shadow: 0 24px 80px rgba(0, 0, 0, 0.28);
transform: translateY(0px) rotate(0deg);
filter: blur(0px);
will-change: transform, filter;
}
.label {
margin: 0 0 12px;
font-size: 0.85rem;
letter-spacing: 0.08em;
text-transform: uppercase;
opacity: 0.7;
}
.velocity-card h1 {
margin: 0 0 12px;
font-size: clamp(2rem, 4vw, 3.5rem);
line-height: 1.1;
}
.desc {
margin: 0;
color: rgba(255, 255, 255, 0.72);
line-height: 1.7;
}
.spacer {
height: 100vh;
}ここでは will-change をつけて、transform と filter が変わることをブラウザに伝えています。
大きな最適化ではありませんが、こうした動きのあるUIではよく使われます。
JavaScript
次に、スクロール速度を取得してカードへ反映します。
const card = document.getElementById("velocityCard");
let lastScrollY = window.scrollY;
let targetVelocity = 0;
let currentVelocity = 0;
function updateVelocity() {
const currentScrollY = window.scrollY;
targetVelocity = currentScrollY - lastScrollY;
lastScrollY = currentScrollY;
requestAnimationFrame(updateVelocity);
}
function render() {
currentVelocity += (targetVelocity - currentVelocity) * 0.12;
const translateY = currentVelocity * 1.5;
const rotate = currentVelocity * 0.08;
const blur = Math.min(Math.abs(currentVelocity) * 0.08, 6);
card.style.transform = `translateY(${translateY}px) rotate(${rotate}deg)`;
card.style.filter = `blur(${blur}px)`;
targetVelocity *= 0.9;
requestAnimationFrame(render);
}
updateVelocity();
render();5.コードの見方
ここでやっていることを順番に整理します。
①前回のスクロール位置を覚える
let lastScrollY = window.scrollY;前のフレームでどこにいたかを記録しておきます。
これがないと差分が取れません。
②現在位置との差分を取る
targetVelocity = currentScrollY - lastScrollY;これが速度の元になります。下に速くスクロールすれば大きめの正の値になり、逆方向なら負の値になります。
③いきなり使わず、なめらかに追従させる
currentVelocity += (targetVelocity - currentVelocity) * 0.12;この部分がかなり大事です。
差分をそのまま見た目に使うと、動きがガタガタしやすくなります。
そこで、今の値を少しずつ目標値へ近づけています。
この考え方は、これまでの easing や Interpolation の記事ともつながります。
補間の基礎を先に整理したい場合は、以下の記事もあわせて読むと理解しやすいです。
④transform と blur に変換する
const translateY = currentVelocity * 1.5;
const rotate = currentVelocity * 0.08;
const blur = Math.min(Math.abs(currentVelocity) * 0.08, 6);速度の値そのものを直接見せるのではなく、
移動量、回転量、ぼかし量に変換しています。
ここはデザイン次第で自由に変えられます。
たとえば、
- 背景だけ少し動かす
- テキストだけ傾ける
- 画像だけブラーをかける
といった応用も可能です。
6.なぜ requestAnimationFrame を使うのか
こうしたアニメーションでは、scroll イベントのたびに直接スタイルを更新するより、
requestAnimationFrame の中で描画をまとめた方が扱いやすいです。
理由は、ブラウザの描画タイミングに合わせて更新できるからです。
毎回イベントの中で全部を処理すると、状態の管理がばらけやすくなります。
requestAnimationFrame の基本がまだあいまいな場合は、こちらの記事もおすすめです。
7.Scroll Reveal や Scroll Story との違い
Scroll Velocity Animation は、これまでのスクロール系UIと似ているようで少し違います。
Scroll Reveal
要素が画面に入ったかどうかを基準にすることが多いです。
「現れ方」を見せる演出です。
Scroll Story
スクロール位置に応じて段階的に内容を切り替えます。
「進行」を見せる演出です。
Scroll Velocity Animation
スクロールの速さに反応します。
「勢い」を見せる演出です。
そのため、主役というよりは、他のUIに重ねて使う補助的な演出として相性が良いです。
8.実装するときの注意点
①やりすぎない
速度に対して移動量やブラーが大きすぎると、読みにくくなります。
特にテキストに強い blur をかけると、一気に使いにくくなります。
②transform を優先する
位置を動かすなら top や margin より、まず transform を使う方が扱いやすいです。
レイアウト全体への影響を減らしやすくなります。
③常に元へ戻る設計にする
スクロールが止まったあとも変形が残ると、不自然に見えます。
今回のように targetVelocity *= 0.9 のような減衰を入れて、自然にゼロへ近づけるのが基本です。
④補間を入れる
差分の生値は思った以上に荒れます。
そのまま使うより、少しなめらかにしてから見た目へ反映した方がきれいです。
9.どんなUIに向いている?
Scroll Velocity Animation は、次のような用途に向いています。
- ファーストビューのカードやビジュアル
- 背景レイヤーの微妙な流れ
- ギャラリーや作品一覧の質感づけ
- ミニマルなサイトの「静かな動き」
- インタラクティブな実験ページ
逆に、フォームや本文のように読みやすさが最優先の場所では、強く入れすぎない方が安全です。
10.実験:スクロール速度でカードの質感を変える
中央のカードがスクロールの速さに応じて少し動き、わずかに傾き、軽くブラーがかかります。
見るポイントは「どこまでスクロールしたか」ではなく、どのくらい勢いよく動かしたかで見た目が変わることです。
観察ポイント
- ゆっくりスクロールすると変化はかなり小さい
- 速く動かすとカードが少し流れる
- スクロールを止めると自然に元へ戻る
- 下方向と上方向で傾き方が変わる
このタイプの演出は、単体では派手すぎないのに、ページ全体の印象を少しだけ上げてくれます。
「何が起きているか説明しづらいけれど、なんとなく気持ちいい」というUIを作りたいときに便利です。
11.まとめ
Scroll Velocity Animation は、スクロール位置ではなくスクロール速度を使って見た目を変えるUI表現です。
実装の流れはそこまで難しくありません。
- スクロール位置の差分を取る
- 速度として保持する
- 補間してなめらかにする
- transform や blur に反映する
これだけでも、かなりそれっぽい動きが作れます。
Scroll Reveal や Scroll Story のような「進行ベース」の演出と組み合わせると、
UIの表現にもう一段階深さを出せます。
まずはカード1枚、背景1レイヤーくらいの小さな実験から始めて、
やりすぎない速度演出を試してみてください。
Scroll Animationシリーズ
- #24 Scroll Reveal Animation
- #25 Scroll Progress
- #26 Scroll Snap Animation
- #27 Parallax Scroll Animation
- #28 Scroll Trigger Animation
- #29 Sticky Scroll Animation
- #30 Scroll Story UI
- #31 Scroll State Machine UI
- #32 Scroll Velocity Animation
- #33 Scroll Mouse Interaction UI
- #34 Scroll Spy UI
- #35 Scroll Sync UI

コメントを残す