こんにちは!フロントエンド・アーキテクトの私です。
Webサイトを作っていて、「なんだかスクロールがカクカクするな……」「アニメーションがスムーズに動かないな……」と頭を抱えた経験、ありませんか? コードは綺麗に書いたはずなのに、なぜか画面の動きがギクシャクする。この「謎のカクつき」の正体、実はブラウザとモニターの裏側の仕組みにあるんです。
今回は、Web制作の現場でも本当によく話題になる「V-Sync(垂直同期)」と「リフレッシュレート」について、難しい専門用語をできるだけ取っ払って、身近な例えを交えながらお話ししていきますね。
大丈夫、一つひとつ紐解いていけば絶対に理解できますから、肩の力を抜いてリラックスして読んでいってください。
—
1. モニターの「パラパラ漫画」とリフレッシュレート
私たちが普段何気なく見ているパソコンやスマートフォンの画面。実はこれ、動画のように滑らかに連続して動いているわけではありません。
身近なもので例えるなら、「超高速のパラパラ漫画」です。
モニターは、1秒間に何回も画面をパッと描き替えることで、まるで絵が動いているかのように私たちに見せています。この「1秒間に何回画面を刷新(リフレッシュ)できるか」を表す数値が、リフレッシュレート(単位はHz:ヘルツ)です。
- 60Hzのモニター: 1秒間に 60回 画面を描き替えます(現代の標準的なディスプレイ)。
- 120Hz / 144Hzのモニター: 1秒間に 120回や144回 も画面を描き替えます(ゲーミングPCや最近のハイスペックスマホでおなじみですね)。
つまり、60Hzのモニターなら、ブラウザは「1秒間に60コマ」の絵を用意してモニターに渡してあげなければいけない、というタイムリミット(制約)が生まれるのです。
—
2. ブラウザとモニターの「すれ違い」が生む悲劇:スタッタリング
さて、ここからが本題です。ブラウザ(レンダリングエンジン)は、JavaScriptを実行したり、CSSを計算してHTMLをDOMやCSSOMというツリー構造に直し、最終的に画面のピクセルを描き出します。
ここで問題が起きるんです。
ブラウザが一生懸命フレーム(絵)を作っているペースと、モニターが「さあ次の絵をくれ!」と急かすペースが、完全にバラバラだったらどうなるでしょうか?
お祭りの屋台を想像してください。
店員さん(ブラウザ)がたこ焼きを焼くスピードと、お客さん(モニター)が容器を持って「ちょうだい!」と手を出すタイミングがズレていたら……?
- たこ焼きがまだ焼き上がっていないのに、お客さんが無理やり容器を出して、中途半端な半熟のたこ焼きを持っていかれる。
- 逆に、たこ焼きは焼けたのに、お客さんがまだ来ていなくて、鉄の上で焦げかけてしまう。
画面の上でこれが起こると、画面が上下にズレて裂けたように見える「ティアリング」や、映像が不規則にカクつく「スタッタリング(引っかかり)」という現象が発生します。これが、Webサイトのスクロールやアニメーションを台無しにする犯人です。
—
3. 救世主「V-Sync(垂直同期)」の仕組み
この「ブラウザとモニターの息が合わない問題」を解決するために生まれたのが、V-Sync(Vertical Synchronization / 垂直同期)という仕組みです。
モニターには、画面の一番上から一番下まで描き終えると、一瞬だけペンを次の上に戻す「休憩時間(ブランキング期間)」があります。V-Syncは、このモニターの呼吸(リズム)に、ブラウザの描画タイミングをピタッと強制的に合わせる技術です。
- 「モニターさん、今から上から下まで描き直すから、ブラウザ君はそのタイミングに合わせて新しい絵を完成させてね!」
- 「了解! じゃあ次の描き始めのタイミング(垂直帰線期間)にぴったり間に合うように絵を渡すよ!」
こうして、交通整理をきちんとすることで、画面のズレや不自然なカクつきを防ぎ、パラパラ漫画を綺麗に見せることができるのです。
—
4. Web制作で私たちが気をつけるべきこと
「じゃあV-Syncに全部お任せしておけば安心だね!」……と言いたいところですが、Webエンジニアやデザイナーには、一つだけ大きな試練があります。
それは、「ブラウザが1コマ(1フレーム)を描くのに許された時間は、60Hzのモニターならわずか『約16.6ミリ秒(1/60秒)』しかない」という現実です。
もし、あなたが書いたJavaScriptの処理が重すぎたり、複雑すぎるCSSアニメーションを指定していたりして、1つのフレームを作るのに「20ミリ秒」かかってしまったとします。するとどうなるでしょうか?
1. 本来なら最初の16.6ミリ秒のタイミングでモニターに絵を渡したかったのに、間に合わない!
2. モニターは「あれ、まだ絵がないな……じゃあ今回は前の絵をもう一回使い回すか」と、同じ絵を2回表示する(コマ落ち)。
3. 結果として、パラパラ漫画が「カクッ」と止まったように見える(スタッタリングの発生)。
これが、Webサイトが重く感じるメカニズムです。
—
実務で使える!滑らかなアニメーションのための実装例
では、このタイムリミット(16.6ミリ秒の壁)を意識しながら、ブラウザに優しい滑らかなアニメーションを書くにはどうすればいいでしょうか?
昔は `setInterval` や `setTimeout` で無理やりアニメーションを動かしていましたが、今はブラウザのレンダリングサイクルと完全に手を取り合って動く、`requestAnimationFrame` という強力なAPIがあります。
これを使って、ブラウザのV-Syncのタイミング(次の描画の直前)に合わせた、優しく効率的なアニメーションの書き方を見てみましょう。
// 【実務で使える!ブラウザの呼吸に合わせた滑らかなアニメーションの実装例】
let position = 0; // 要素の現在の位置を保持する変数
const box = document.querySelector(‘.target-box’); // 動かしたいHTML要素を取得
// アニメーションの1コマ分の処理を行う関数
function step(timestamp) {
// positionを少しずつ進めて、要素を右に動かす
position += 2;
// 実際にCSSのスタイルを書き換えて画面を更新する
box.style.transform = `translateX(${position}px)`;
// もし画面の端(例: 500px)に到達していなければ、次のフレームでもう一度この関数を呼ぶ
if (position < 500) {
// ★重要:ここがポイント!
// setTimeoutではなく requestAnimationFrame を使うことで、
// ブラウザのV-Sync(描画のタイミング)に合わせて賢く次の処理を実行してくれます。
requestAnimationFrame(step);
}
}
// アニメーションを開始するトリガー
// ブラウザが「次の絵を描く準備ができたよ」という絶妙なタイミングで step 関数を呼び出してくれます
requestAnimationFrame(step);
この `requestAnimationFrame` を使えば、ブラウザが裏でどんなに忙しくても、モニターのリフレッシュレートやV-Syncのタイミングに合わせて無駄なくフレームを刻んでくれるため、CPUやGPUへの負荷を最小限に抑えつつ、最も滑らかな動きを実現できます。
---
まとめ
- リフレッシュレート(Hz): モニターが1秒間に画面を描き替える回数(パラパラ漫画のペース)。
- V-Sync(垂直同期): ブラウザの描画タイミングとモニターの呼吸をピタッと合わせる交通整理の仕組み。
- スタッタリング(カクつき): 処理が重すぎて1フレームの制限時間(60Hzなら約16.6ミリ秒)に間に合わなくなると発生する。
- 対策: `requestAnimationFrame` などのブラウザの仕組みに寄り添ったAPIを使い、無駄な負荷をかけずにスマートなコードを書くことが大切。
「動かない」「カクカクする」という現象に出会ったときは、ぜひ今回お話しした「ブラウザとモニターのタイムリミット」を思い出してみてください。
大丈夫、仕組みさえ分かってしまえば、あなたの書くWebサイトはもっともっと滑らかで気持ちの良いものに生まれ変わりますよ。今日のコーディングから、ぜひ意識してみてくださいね!

コメント