shiftB
instagramyoutube
運営会社プライバシーポリシー特定商取引法に基づく表記JavaScript学習サイト JS Gym
お問い合わせ
©2025 bubekichi inc.

ブラウザのレンダリングの仕組み

0
Threads
受講生ブログ

ブラウザのレンダリングの仕組み

icon
kento

ブラウザのレンダリングの仕組み

投稿日: 2025年07月10日

Tips
要約
  • ブラウザのレンダリングプロセスは、HTMLとCSSの解析から始まり、スタイル適用、レイアウト計算、ペイント、最終的な合成の順に行われる。
  • フレームレートが60fpsの場合、1秒で約16.6ミリ秒ごとに画面が更新され、動きが滑らかになるが、重い処理があるとフレームレートが低下しカクつく。
  • アニメーションを滑らかに表示するためには、transformやopacityを使用し、メインスレッドの負担を軽減することが重要である。
音声で記事を再生
0:00

はじめに

ShiftBのカリキュラムで、Reactの勉強しているとレンダリングという言葉を聞くと思います。 コンポーネントがHTML要素として画面に表示される過程のこと。

例えば、データや状態が更新されると、自動的に変更部分が再レンダリングされ、画面に反映される仕組みです!

このように普段便利なライブラリを使っているけど、じゃあブラウザ側でのレンダリングの仕組みってどうなっているの? ブラウザの仕組みを知ることで、パフォーマンス向上の勉強になりそう!っと思って、 今回、ブラウザのレンダリングの仕組みについて書こうと思います。

内容が長めなので、読むのめんどくさいです笑


導入(パフォーマンスとフレームレート)

ここでは、どのように画面に表示されて便利なライブラリやアニメーションが表示されるようになっているのかをパフォーマンスとフレームレートの関係について見ていきます!

例えば、アニメーションとか使ってUIを作って画面に表示させる時、パフォーマンスが悪く動きがカクカクしたり、スクロールがカタついたりするのはなぜでしょう?
これはフレームレートの低下が原因で起こります。
フレームレートはfps(frames per second)という単位で表します。
この数字が低ければ低いほど、動きが悪くカタつくってわけです。

例えるなら、パラパラ漫画を想像してください。 枚数が少ないと動きはカタつくが、枚数が多ければ多いほど動きが滑らかになりますよね? なので、これと同じで、フレームレートが低下するというのは、「フレーム数が減る=パラパラ漫画のページ数が少なくなる」状態なので、動きがカクついて見えるということなのです。

ブラウザの場合60fpsが最高となり、パフォーマンス的に良い状態と言われています。 これは、一秒間に60回画面が更新されていることになります。

スクロールする動きやアニメーションの動きは、静止画面を高速で切り替えることで、 動いているように表示させている仕組みです。 ※高リフレッシュレート環境では、それ以上のfpsになることもある。

ブラウザのレンダリングの仕組み|ShiftBブログ

60fpsということは、

  • 1秒を60で割ると…

    → 1回の更新にかかる時間は約16.6ミリ秒(= 1000ミリ秒 ÷ 60)

    60fps = 約16.6msごとに1回画面が切り替わる

    → この速さで画面が更新されているから、滑らかに見える!

しかし、JavaScriptやレンダリングに重い処理があると、画面更新の処理までに間に合わず、 フレームレートを低下させてしまいます。 これがカタつき、劣化につながるのです。

つまり、ブラウザで画面のパフォーマンスが悪いとなった場合、16ms以内に処理を完了していないってことになるので、重い処理がないか、頻繁に呼ばれている処理がないかなどを見ていくことになります。

ブラウザのレンダリングの仕組み|ShiftBブログ

JavaScriptを改善する場合は自分の書いたコードの負荷の重いところをDevTools (開発者ツール) で見つけて改善する方法もありますが、レンダリングはブラウザ側の処理ではブラックボックス化(中身が見えない)ため、基礎知識がないと修正するのは困難かもしれないです。 こういったところから、レンダリングの知識は問題解決として有効になります。

ブラウザ処理のフロー

下の図は、ブラウザが各フレームごとに行なっている処理となります。(レンダリングの代表的な処理でもあります) この処理は、ブラウザのコアな部分のメインスレッドです。
スレッドとは、プログラムが起動してから処理を実行し終えるまでのことです。

ブラウザでは、Parse(パース) > Style(スタイル) > Layout(レイアウト) > Paint(ペイント) > Composite(コンポジット)の流れで、画面にどのように表示させるのかを計算しています。

ブラウザのレンダリングの仕組み|ShiftBブログ

例えば、画面表示の際にはブラウザはこの処理フローを最初から行います。
逆に画面表示内容に更新があった場合は、必要な工程のみ処理し、再計算が不要な工程は省略します。 ということは、どのフロー関連しているのかを知っているだけで、ブラウザの負担を大きく減らすことができます。

それでは、それぞれの関係を見ていきましょう!

Parse

Parseでは、HTMLとCSSの構文解析が行われます。
ブラウザはHTMLとCSSを平行して構文解析し、 DOM Tree(ドムツリー)とStyle Rules(スタイルルールズ)という処理しやすい構造体に変換します。

つまり、これらの構造体を生成するのがParseの役割です。
表示する対象のコンテンツを解析する処理をする部分です。

DOM Treeの作成

ブラウザのレンダリングの仕組み|ShiftBブログ

HTMLをパース(解析)して、DOMツリーを作成します。 DOMツリーの一番上は、documentになります。

Style Rulesの作成

ブラウザのレンダリングの仕組み|ShiftBブログ

CSSをパースして(解析)、HTMLと同じようにツリー構造にして、Style Rulesを作成します。

DOMとは?

ドキュメントオブジェクトモデル (Document Object Model, DOM) は、ウェブページを表す HTML のような文書の構造をメモリー内に表現することで、ウェブページとスクリプトやプログラミング言語を接続するものです。

余談

ブラウザのレンダリングを担当する機能をレンダリングエンジンと呼びます。 SafariはWebkit、ChromeはBlink、FirefoxはGecko、EdgeはEdgeHTMLというそれぞれのレンダリングエンジンが使用されています。 それぞれブラウザのレンダリング処理フローが異なるため、ブラウザによる挙動の違いがあります。

Style

続いては、Styleの工程です。
この工程では、先ほど作成してDOM TreeとStyle Rulesの紐付けが行われます。
具体的には、どのスタイルがどの要素に適用されるかをマッチングし、複数個のスタイルが 一致する要素に関しては、スタイル適用の優先順位に従って最終的に適用されるスタイルを 割り出します。

この作成したものを次のLayoutで描画させます。

ブラウザのレンダリングの仕組み|ShiftBブログ

ここでできた、スタイルと要素をマッチングはRender Tree(レンダーツリー)と呼ばれます。 Render Treeの各要素をRenderer(レンダラー)と呼びます。

Layout

ブラウザのレンダリングの仕組み|ShiftBブログ

レイアウト(Layout / Reflow)の工程について

先ほど作成された Render Tree(レンダーツリー) によって、
「どの要素にどのスタイルが適用されているか」がブラウザに伝わります。

この次の工程では、各要素の 位置と大きさを計算 します。
この処理は Layout(レイアウト) または Reflow(リフロー) と呼ばれます。


レイアウト計算の流れ

  • レンダーツリーの 上流から下流(親→子)に向かって 再帰的に計算されます。

  • 初回のページ表示時には、最上位の <html> タグから順に、階層ごとにすべての要素を処理していきます。


再レイアウト(更新時)

画面が更新される場合(例:JavaScriptで要素を追加・変更したとき)、
ブラウザは できるだけ計算範囲を最小限に抑える ようにします。

そのため再計算が必要になるのは、次のような範囲に限定されます:

  • 変更があった要素自身

  • その子要素

  • 同じ階層の兄弟要素

ブラウザのレンダリングの仕組み|ShiftBブログ

Layoutの工程では、最終的に Layout Tree(レイアウトツリー)が作成されます。

Layout Tree とは、ブラウザが「何をどこに表示するか」を計算するために生成する構造で、画面に実際に表示される要素のみが含まれます。

たとえば、display: none が指定された要素は完全に無視され、Layout Tree には含まれません(DOMには存在するが、レイアウト処理には登場しません)。

一方で、visibility: hidden のように画面上は見えないがスペースが確保される要素は
Layout Tree に含まれます。

さらに、::before や ::after などの擬似要素も、視覚的に表示されるためレイアウト対象として扱われます。

つまり、Layout Tree には「画面に描画される要素」だけでなく、「レイアウトに影響を与える要素」も含まれるのが特徴です。


🧠 Global LayoutとIncremental Layout

Layout の計算には、大きく以下の2種類があります。

  • Global Layout(グローバルレイアウト)

    ページ全体に関わる変更(例:ブラウザの幅変更、フォントサイズの変更など)により、全体のレイアウトが再計算されます。そのため負荷が大きめです。

  • Incremental Layout(インクリメンタルレイアウト)

    一部の要素に限定された変更(例:要素の追加や削除)に対して実行される、軽量なレイアウト計算です。Global Layoutと比べ、軽い処理になります。

この Layout の再計算は、JavaScript によって要素の位置やサイズが変更されたとき、またはレイアウトに関係する以下のような スタイルプロパティが変更されたとき に発生します。


🔧 Layout に影響する代表的な CSS プロパティ:

height, width, padding, margin, top, right, left, bottom, box-shadow など。

Paint(ペイント)

ブラウザのレンダリングの仕組み|ShiftBブログ

Parse > Style > Layout を経て、要素を出力する位置や大きさ、色が変わります。
Paintは、簡単に言うとabsoluteやfixedといった、要素と要素が重なる時にどっちを上にするのかを加味しながら画面を生成する役割です。

Paintの工程では要素の重なりを考慮して、順番に命令を作成することで正しく描画できるようにします。 この命令をPaint Records(ペイントレコーズ)と言います。

Paint Recordsの作成

Pain Recordsの命令の順番は、「Stacking Contexts(スタッキングコンテキスト)」をもとに決定されます。 スタッキングコンテキストでは、要素の出力順を保持します。
どっちの要素を先に描写させるのかを命令する役割です。
下の図を見てください。 右側にある、ペイントレコーズによって要素の重なり順によって生成されます。 背面に来る要素を先に命令に出して、どんどん上書きしていけば全面に来るものが画面上に来る仕組みとなってます。

ブラウザのレンダリングの仕組み|ShiftBブログ
  • 背面要素 → 先にペイント

  • 前面要素 → 後からペイント(上書きされる)

  • DOM順や z-index に基づいて ペイント順序 が決まる

  • Paint Records はこの描画指示を保持する


🖼 イメージで言えば:

絵を描くときに「背景」→「人物」→「文字」みたいに、下から順に重ねて描いていくのと同じです。

Layer Treeの作成

モダンブラウザでは同時にLayer Tree(レイヤーツリー)を作成します。
Layerの分離は変更の際の計算量を少なくするためにとても有効です。
例えば、Layerを分離せず描写を行った場合、変更があった際に他の要素との変更を考慮して多くの計算を行う必要があります。
しかし、レイヤーを分離して他の要素を考慮しないでよい状態にしておくと、そのレイヤーのみ再計算を行えば良いことになり、計算量を大幅に削減できるようになります。
つまり、レイヤーを分割することによってパフォーマンス向上になるってことです。

ブラウザのレンダリングの仕組み|ShiftBブログ

ポイント

Layer Treeのレイヤーを分離する条件に先ほどのz-indexは、関係ないです。
3Dトランスフォームtransform: translateZ(0)やtransformを使用したアニメーションを検知した際にブラウザはレイヤーを分離します。 
また、will-changeを使用した場合にもLayerは分けられます。
ここまでの処理がブラウザのMain Thread(メインスレッド)上で行われます。最終的に作成されたLayer TreeやPain Recordsは、Compositor Thread(コンポジタースレッド)に渡され、Main Threadは開放されます。


Composite(コンポジット)

レイヤーの合成とラスタライズ

Webページの描画の最後のステップが「Composite(合成)」です。

まず、Main Thread(メインスレッド)が「何をどう描くか」の命令(Paint Records)を作ります。
その命令をもとに、Compositor Thread が「どの部分を再描画するか」を判断し、レイヤー単位で描画の準備をします。

続いて、Raster Thread が各レイヤーをピクセル単位で画像化します(これをラスタライズと言います)。この処理は複数スレッドで並列に行われます。

最後に、GPU がすべてのレイヤー画像を重ねて、1枚の画面に合成します。これがユーザーに表示されるWebページです。

ブラウザのレンダリングの仕組み|ShiftBブログ

アニメーションによく利用されるtransform、opacityの適用もこの工程で行われます。そのためtransform, opacityの変更はレイアウトプロパティー(left,topなど)の変更に比べて、軽い処理となります。


Compositeに関係の深いプロパティー

transform, opacity

余談

例えば、Layoutの部分で、物体の位置を変えたとき、アニメーションで変更したするとLayoutの工程に作用されます。 
つまり、後続のPaintやCompositeの処理も再計算されるためパフォーマンスが悪くなる。 アニメーションを使うなら、Compositeの工程で使うことがおすすめ。

ポイントで理解

1. 誰が処理する?

  • Compositor Thread(コンポジタースレッド):

    メインスレッドの代わりに描画を担当

  • Raster Thread(ラスタースレッド):

    レイヤーごとの画像を**ピクセル単位で塗る(ラスタライズ)**担当


2. 何をする工程?

  • Paint Records をもとにレイヤーを合成

  • レイヤーごとにピクセルデータを生成(=ラスタライズ)

  • 最後にすべてのレイヤーを重ねて1枚の画面を作成(合成)


3. なぜ分担してる?

  • ページ全体にわたるような大きなレイヤーもある

  • 計算負荷が高いため、1スレッドでは間に合わない

レンダリングとスレッド

下図のように、レンダリングの工程によってブラウザは異なるスレッドを使用します。
レンダリングは、ほとんどがMain Treadで行われます。
Compositeから、Compositor ThreadやRaster Thread 4スレッドほどあります。(ブラウザによる)

最終的にGPUに指示が送られる。

ブラウザのレンダリングの仕組み|ShiftBブログ

🧠 Main Thread(メインスレッド)

Webページを表示するうえでの「司令塔」。

HTMLの解析、CSSの適用、レイアウト、描画命令の生成(Paint)など、基本的な処理をすべて担当します。

JavaScriptの実行もこのスレッドで行われるため、負担が大きく、なるべく仕事を減らすことが重要です。


🎬 Compositor Thread(コンポジタースレッド)

画面のレイヤーをまとめて1枚に合成する担当。

自分でピクセルを塗るのではなく、Raster Threadに「塗って」と依頼します。

塗り終わったレイヤーを集めて、重ね順に合成して画面を作ります。

なお、アニメーションでレイアウトが変わるときなどは、Main Threadが一時的に合成処理を担当することもあります。


🖌️ Raster Thread(ラスタースレッド)

レイヤーを画像に変える担当(これを「ラスタライズ」と言います)。

複数(通常4つ)のスレッドが並列で動き、Compositor Threadから来た塗りの依頼を高速で処理します。


🖥 GPU(グラフィック処理装置)

最終的に画面に表示する役割を担います。

特に transform や opacity を使ったアニメーションでは、レイヤーはすでにできていて、Main Threadを使わずにGPUだけで描画できるので、高速で滑らかに動きます。

ブラウザはこのようにスレッドを分けることで画面表示を最適化しています。

💡 ケーススタディ:要素を変えるとブラウザで何が起きる?

HTMLやCSSの変更は、ブラウザ内で「Style → Layout → Paint → Composite」というステップを踏んで画面を描画します。

JavaScriptでスタイルを変更するとき、どのステップに影響するかによって処理の重さが変わるのがポイントです。

JavaScriptである要素の高さを変更した場合

ブラウザのレンダリングの仕組み|ShiftBブログ

🔁 起こる処理

  • Style → Layout → Paint → Composite の全工程が再実行されます。

  • 位置やサイズを再計算する Layout に関わるため、特に処理が重くなります。

  • 子要素が多いとその分、再計算も増えるので注意!

🔥 注意点

  • height, width, margin, padding, top, left などの変更はLayoutに影響。

  • Layoutは Main Thread(メインスレッド)で動くため、JavaScriptの他の処理も詰まりやすい。

  • アニメーションには使わない方が良い。代わりに transform を使う。

  • もし使うなら、will-change でパフォーマンスを最適化する。

✅ 要素の色を変更した場合(Paintが関わる変更)

🔁 起こる処理

  • Layoutはスキップされ、Paint → Composite が実行されます。

  • Layoutよりは軽いですが、Main Thread上で動くので、負荷が高い場合もありえます。

ある要素の色を変更した場合

ブラウザのレンダリングの仕組み|ShiftBブログ

ある要素の色を変更した場合、Layout(位置や高さ)は関係ないのでスキップされます。
Paint、Compositeが呼ばれます。
Layoutの処理がない分、先ほどより処理時間は短くなりますが、 Main Threadは変わらず使用されるので、処理が重くなるとこがあります。
そのため、処理が軽く済むopacityを代用するのがおすすめ!

Paintに関わる要素

background-color, background-image, border-color, colorなど

🔥 注意点

  • background-color, border-color, color などはPaintに関係。

  • 可能なら opacity で代用するのがおすすめ(より軽い処理で済む)。

  • どうしてもPaint処理が必要なら will-change を使って負荷を減らす工夫を。

✅ transformでアニメーションした場合(Compositeのみ)

🔁 起こる処理

  • transform や opacity の変更は、Composite のみが関わる。

  • この工程は Compositeスレッドで処理されるため、Main Threadに影響を与えません。

  • その結果、アニメーションが 非常に滑らかになります。

Compositeに関わる要素

transform, opacity

🔥 注意点

  • transform, opacity はパフォーマンスに優しい。

  • アニメーションや動的な変化には transform を優先的に使うべき。

  • ただし、ブラウザによっては違いがある(例:Safariでは transform でもLayoutが再計算されることがある)。

以下のリンクで、どのプロパティーがどの工程に作用されているのかが確認できます。
興味がある人は、覗いてみてください。

Chrome Devtools による フロントエンドパフォーマンスの計測に参考となる記事となります。


さいご

ここで紹介したものは、実際にレンダリングエンジンによって異なるので絶対ではないですが、 基本的な仕組みを理解するとレンダリングに負担をかけずに実装が行えます。
トラブルが起こった際には、見るべきところがわかってくるので、解決につながる材料になると思います。

0

シェア!

Threads
icon
kento
プロフィールを見る
Loading...
記事一覧に戻る
Threads
0

関連記事

自分情熱大陸 -感謝を伝えたいと思い、書きました-

icon
tomoe

AIがコードを書く時代だからこそ、プログラミングを学ぶべき理由

icon
タマネギ

TAの使い方

user
吉本茜

白菜先生の話 -プログラミングの楽しさを教えてくれた人-

icon
tomoe

BRAVE 〜AIネイティブ世代が考える、エンジニアの未来|第1話〜

user
青栁幸助

BRAVE 〜AIネイティブ世代が考える、エンジニアの未来|第2話〜

user
青栁幸助

最新記事

子育てと仕事が両立できない現実 ー 6月の葛藤

user
吉本茜

7ヶ月かけてアプリを完成させた話。やってよかったことと振り返り

icon
まえたく

「Next.js の (dashboard) は何者?URLに出ないフォルダの正体と活用法」

icon
さかした

URIと文字

icon
kento

時短!Gitコマンドをスマートに打てる「エイリアス」

user
吉本茜

BRAVE 〜AIネイティブ世代が考える、エンジニアの未来|第4話 人生、空回りまくり編Part1〜

user
青栁幸助