パフォーマンス制約から考えるJavaScript vs CSS|現場で本当に使い分けるべき判断軸
こんにちは!
今日は「パフォーマンス制約から考えるJavaScript vs CSS」について解説します。
僕が経験した、パフォーマンス地獄の話
正直に白状します。
僕も昔、JavaScriptでめっちゃ凝ったアニメーションを作ってしまって、本番環境で動作がもたついた経験があります。
クライアントから「スマートフォンでスクロール時にカクカクするんですけど」という指摘を受けて、原因を調べたら、JavaScriptで毎フレーム要素のプロパティを動的に変更していたんです。
その時の教訓が「パフォーマンスの観点から、JavaScriptとCSSをちゃんと使い分けなあかん」ということ。
アニメーションやインタラクションを実装する時点で、CSSSで完結できるのか、JavaScriptが必要なのかを判断することが、後々のトラブル回避につながるんですよ。
今は現場で後輩たちにもこの視点を教えているんですが、意外と「アニメーションだからJavaScript」みたいに何も考えずに実装しちゃう人が多いんです。
ほんま勿体ないです。
レンダリングフローから考える選択基準
ブラウザのレンダリングフローを理解すると、JavaScriptとCSSの使い分けの理由が見えてきます。
簡単に説明しますね。
CSSアニメーション・トランジションの場合:
transform や opacity を使ったCSSアニメーションは、GPUで処理されることが多いです。
つまり、JavaScriptがいちいち関与せず、ブラウザのレンダリングエンジンが効率的に動かしてくれるわけです。
このため、フレームレートが安定しやすく、バッテリー消費も少ないです。
JavaScriptで毎フレーム更新する場合:
requestAnimationFrame() を使って style.left や style.width を変更すると、毎フレームJavaScriptが実行されます。
その結果、レイアウト再計算(リフロー)が発生して、パフォーマンスが落ちることがあります。
特にモバイルデバイスでは顕著です。
現場で実際に見てきたのは、スクロール時に要素の位置を style.transform で動かす場合と、style.top で動かす場合で、体感できるほど差が出たケースです。
同じくらい複雑なアニメーションでも、どのプロパティを操作するかで「滑らかに動く」「カクカクする」が決まっちゃうわけですよ。
判断基準をまとめるとこうです:
transformやopacityのアニメーション → CSSで実装する- 要素の追加・削除が伴うインタラクション → JavaScriptが必要
- ユーザー操作に即座に反応する複雑な状態管理 → JavaScriptが適切
- 単純なホバー時の色変化・サイズ変化 → CSSのみで十分
- スクロール検出での条件付きアニメーション → CSSだけでは難しい場合が多い
モバイルデバイスでの実測値で判断する
ここからが、ほんまに大事なポイントです。
パソコンのブラウザでは「大丈夫そう」に見えても、モバイルデバイスで試すと全然違うということ、めっちゃあります。
僕は案件ごとに、Chrome DevToolsのパフォーマンスタブで実際に計測するようにしています。
具体的には、Frames Per Second (FPS) が 60フレーム以上を保てているかを見ます。
60FPS以下に落ちると、ユーザーには「何か引っかかる」と感じられるんです。
特に確認すべき項目はこれです:
- JavaScript実行時間:JavaScriptで毎フレーム
50ms以上かかってないか - レイアウト時間:レイアウト再計算が頻繁に発生していないか
- ペイント時間:画面の再描画にどれくらい時間がかかっているか
- 複合処理時間:複数の要素が同時にアニメーションしている時の負荷
実測の例を出すと、あるクライアントの商品一覧ページで、スクロール時に商品画像をフェードインさせる実装がありました。
最初はJavaScriptで opacity を変更していたんですが、パフォーマンス計測で FPS が 40 まで落ちてました。
それを CSS の scroll-behavior と Intersection Observer API を組み合わせて、CSSアニメーションで実装し直したら、FPS が 58 まで改善されたんです。
ほんま違う。
もう一つの判断基準として、アニメーション中に状態管理が必要かを考えるといいですよ。
例えば、「ボタンをクリックしたら、複数の要素が異なるタイミングで動く」みたいな複雑な挙動は、CSSだけでは管理しきれません。
こういう時こそ、JavaScriptで data-state 属性を変更して、CSSセレクタで条件分岐させる方法が現実的です。
まとめ
JavaScriptとCSSの使い分けって、「どちらが楽か」ではなく「どちらがパフォーマンスを損なわないか」で判断するのが正解です。
現場で何度も見てきたのは、「アニメーション = JavaScript」という固定観念が、後々のバグやパフォーマンス問題を生むということ。
逆に、最初から「CSSで できるなら CSS で、JavaScriptの状態管理が必要なら JavaScript」という思考で実装すると、保守性も良くなります。
大事なのは、実装する前に一呼吸置いて「このアニメーション、ほんまにJavaScript が必要?」と問い直すことですよ。
その習慣が、品質の高いフロントエンド開発につながるんです。
Web制作で困ったことがあったら、またこのブログを覗いてくださいね!
― クリオ