هر صفحهٔ وب که در مرورگر میبینیم، نتیجهٔ یک فرآیند چندمرحلهای است که به آن Rendering Pipeline گفته میشود. این فرآیند تعیین میکند مرورگر چگونه از کدهای خام HTML، CSS و JavaScript به تصویری قابل مشاهده روی صفحه تبدیل میشود.
درک درست این مراحل برای توسعهدهندگان بسیار مهم است زیرا:
میتوانیم علت کندی یا سنگینی UI را بفهمیم
میدانیم Reflow، Repaint و Composite دقیقاً چه زمانی اتفاق میافتند
متوجه میشویم رفتارهای CSS مثل z-index، stacking-context، position، flex، grid، transform و responsive layout چگونه توسط مرورگر محاسبه میشوند
یاد میگیریم چرا تغییر اندازهٔ صفحه باعث layout دوباره میشود
مرورگر از چند بخش کلیدی تشکیل شده است:
وظایفش شامل دانلود HTML، CSS، JS، فونتها و تصاویر است.
این مرحله فقط مسئول دریافت دادههاست.
این لایه مسئول مراحل مربوط به ساخت ساختاربصری صفحه است که شامل مراحل زیر میشود :
ساخت DOM
ساخت CSSOM
ادغام DOM + CSSOM و ساخت Render Tree
محاسبه Layout
مرحله Paint
مثل V8 در کروم.
تمام کد JavaScript در این لایه اجرا میشود.
نکته مهم: JS ممکن است Render Engine را مجبور به Reflow یا Repaint کند (مثلاً با تغییر style ها یا اندازهها).
این لایه، تمام لایههای گرافیکی ساختهشده را از GPU گرفته و روی هم میگذارد (Composition) تا فریم نهایی ساخته شود.
در ادامه به ساخت ساختار بصری صفحه و compose کردن تمام لایه ها خواهیم پرداخت. این مراحل از وظایف لایه Render Engine و Compositor است .
همانطور که در سطور بالا توضیح داده شد لایه Render Engine مسئول ساخت ساختار بصری صفحه است و بخش Compositor هم لایه های گرافیکی ساخته شده در Render Engine را روی هم میگذارد.
شش مرحله زیر پس از دریافت فایل html از طریق لایه شبکه اتفاق میافتد و باعث نمایش صفحه میشود
لایه اجرا: HTML Parser
مرورگر HTML را خط به خط میخواند، تگها را شناسایی میکند و درخت DOM ساخته میشود.
<body> <header></header> <main></main> </body>
تبدیل میشود به:
DOM Tree └─ body ├ header └ main
DOM فقط ساختار “محتوا” را نشان میدهد، نه ظاهر آن.
لایه اجرا: CSS Parser
CSS فایلها خوانده و تبدیل به مجموعه قوانین (CSSOM Tree) میشود:
main { display:flex; gap:20px } header { height:60px; background:#000 }
تبدیل میشود به
CSSOM Tree ├ header { height:60, bg:black } └ main { display:flex, gap:20 }
بدون CSSOM امکان شروع Layout وجود ندارد.
لایه اجرا: Render Engine
Render Tree فقط شامل المنتهایی است که روی صفحه نمایش داده میشوند.
مثال: اگر بخشی display: none باشد در Render Tree وجود ندارد.
Render Tree موارد زیر را نگه میدارد:
چه چیزی چه اندازهای دارد
چه نوع باکسی است
چه استایلی رویش اعمال شده
این مرحله جایی است که مفاهیمی مثل:
position
flex
grid
float
z-index
stacking context
برای اولین بار معنی پیدا میکنند.
فرض کنید این HTML و CSS را داریم:
<body> <header class="top">Title</header> <main> <section class="hero"></section> <div class="hidden"></div> <p>Hello</p> </main> </body>
.top { height: 60px; background: black; } .hero { width: 100%; height: 300px; background: blue; } .hidden { display: none; } p { color: red; font-size: 20px; }
DOM Tree که ساخته میشود به شکل زیر است:
DOM Tree └ body ├ header.top └ main ├ section.hero ├ div.hidden └ p
همانطور که مشاهده کردید DOM همه عناصر را شامل میشود از جمله (even those with display:none.)
CSSOM Tree:
CSSOM ├ .top { height:60px; background:black } ├ .hero { width:100%; height:300px; background:blue } ├ .hidden { display:none } └ p { color:red; font-size:20px }
Render Tree (نتیجه واقعی ادغام DOM + CSSOM) در مثال بالا:
Render Tree فقط شامل چیزهایی است که واقعاً باید روی صفحه دیده شوند.
display:none حذف میشود.
اما visibility:hidden حذف نمیشود (فقط نامرئی است).
پس Render Tree میشود:
Render Tree └ [body] ├ header.top → height:60 → background:black └ [main] ├ section.hero → width:100% → height:300 → background:blue └ [p] → color:red → font-size:20 → text:Hello
در این مرحله هنوز موقعیت دقیق روی صفحه هنوز مشخص نشده است. این امر وظیفهی مرحلهی Layout است.
این مرحله تعیین میکند هر عنصر دقیقاً در کدام موقعیت قرار بگیرد و چه اندازهای داشته باشد.
لایه اجرا: Render Engine (مرحله Geometry)
در Layout:
Flexbox چیدمان عناصر child را حساب میکند
Grid نواحی را محاسبه میکند
position: relative حرکت محاسباتی دارد (بدون خروج از flow)
position: absolute از نزدیکترین ancestor دارای position استفاده میکند
تغییر اندازه صفحه مستقیماً Reflow را فعال میکند
مثال:
main { display: flex; gap: 20px; }
در این مرحله مرورگر موارد زیر را محاسبه میکند:
آیتم اول چند پیکسل عرض دارد
آیتم دوم از کجا شروع میشود
فاصله ۲۰px دقیقاً کجاست
حتی responsive نیز در مرحله Layout اتفاق میافتد؛
زیرا تغییر اندازه صفحه، Media Queryها و محاسبات flex/grid را تغییر میدهد.
Flexbox در مرحلهی Layout چه میکند؟
Flexbox در زمان Layout تصمیم میگیرد هر child در چه جهتی، با چه فاصلهای و با چه اندازهای قرار بگیرد.
مرورگر بر اساس قوانین Flex مثل flex-direction، justify-content، align-items و flex-grow پهنا و ارتفاع نهایی هر آیتم را محاسبه میکند.
به زبان ساده:
Flexbox مغز چیدمان افقی/عمودی و اندازهدهی پویا است.
Grid یک مرحله جلوتر میرود:
مرورگر ابتدا یک شبکه (grid) میسازد، همه trackها (سطرها و ستونها) را اندازهگیری میکند و سپس هر عنصر را در خانه مخصوصش میگذارد.
به زبان ساده:
Grid معمار صفحه است؛ ساختار، ردیف و ستون را تعیین میکند.
المانهایی که position:relative دارند جای اصلیشان در flow حفظ میشود.
اما میتوانند با top/right/... کمی جابجا شوند.
مرورگر ابتدا مکان معمول عنصر را حساب میکند،
بعد یک جابجایی کوچک تصویری روی آن اعمال میکند.
به زبان ساده:
relative جای عنصر را عوض نمیکند؛ فقط کمی آن را در همان جای خود تکان میدهد.
المانهای absolute از جریان عادی صفحه (normal flow) خارج میشوند.
مرورگر ابتدا نزدیکترین ancestor که position دارد را پیدا میکند (relative/absolute/fixed) و سپس جای دقیق عنصر را نسبت به آن حساب میکند.
به زبان ساده:
absolute خودش را از بقیه جدا میکند و مکانش را براساس والد پوزیشندار تعیین میکند.
چون Layout وابسته به اندازه viewport است: width, height, درصدها، flex، grid، media queries و …
در نتیجه:
وقتی اندازه صفحه تغییر میکند، مرورگر مجبور است دوباره همه اندازهها و چیدمانها را از اول محاسبه کند.
به زبان ساده:
Resize یعنی محاسبه دوباره کل چیدمان → Reflow کامل.
Paint مرحلهای است که مرورگر:
رنگها
border
shadows
background
متن
را روی لایهها نقاشی میکند.
اینجا اولینبار توضیح پرسش مهم تو روشن میشود:
Paint فقط رنگ زدن نیست
مرورگر اینجا تصمیم میگیرد کدام عنصر روی کدام عنصر قرار بگیرد و چه چیزی باید قبل یا بعد کشیده شود.
مثلاً:
اگر سه div داشته باشیم:
div1
div2
div3 با z-index: 999
مرورگر باید تصمیم بگیرد:
اول div1 کشیده میشود بعد div2 آخر div3
این کار بخشی از Paint Order و قوانینی به نام Stacking Context است.
در این مرحله:
لایههای گرافیکی از Render Engine دریافت میشوند
GPU آنها را روی هم قرار میدهد
فریم نهایی ساخته میشود
این دقیقاً همانجایی است که:
«در نهایت چی روی چی میافتد»
«ترکیب لایهها چطور انجام میشود»
تعیین میگردد.
اگر transform یا opacity داشته باشیم، مرورگر برای آنها یک composite layer جدا میسازد و GPU آنها را بدون Reflow دوباره جابهجا میکند.
مرحله ۱ تا ۳ — DOM, CSSOM و Render Tree:
این مراحل شبیه کشیدن نقشه ساختمان هستند. اسکلت ساختمان و فضاها مشخص میشوند، کجا اتاقها هستند و چه دیوارهایی وجود دارد، ولی هنوز جزئیات روی زمین قرار نگرفتهاند.
مرحله ۴ — Layout / Reflow:
در این مرحله، مرورگر جای دقیق اجزا را محاسبه میکند.
دیوارهای کناف، پارتیشنها، کابینتها و میزها اندازهگیری و در جای خود قرار میگیرند. مانند این است که معمار میگوید هر وسیله دقیقاً کجا باشد و چه اندازهای داشته باشد.
مرحله ۵ — Paint:
حالا مرورگر اجزا را رنگآمیزی و طراحی میکند.
مثل رنگ کردن دیوارها، قراردادن کفپوش، تابلوها، و جزییات بصری مانند میزها و کابینتها.
مرحله ۶ — Compositing:
در این مرحله، همه لایهها روی هم چیده میشوند و فریم نهایی نمایش داده میشود.
مانند کشیدن پرده روی پنجرهها یا مشخص کردن اینکه کدام وسیله روی کدام قرار گیرد و چه چیزی در دید کاربر برتر است.
Reflow (یا Layout) زمانی اتفاق میافتد که مرورگر مجبور شود مکان و اندازه عناصر را دوباره محاسبه کند.مثلا زمانی که اندازه مرورگر را تغییر میدهیم.
چه تغییراتی Reflow را ایجاد میکنند؟
هر تغییری که بر هندسه یا ساختار صفحه تأثیر بگذارد باعث Reflow میشود:
تغییر width, height, padding, margin
تغییر محتوای متن (مثلاً اضافه شدن متن طولانی)
تغییر position (relative, absolute)
تغییر display یا float
تغییرات Flexbox یا Grid
تغییر اندازه مرورگر یا Media Query
تصور کنید یک div داریم:
<div id="box">Hello</div>
#box { width: 100px; height: 100px; padding: 10px; border: 2px solid black; }
اگر JS مقدار width را تغییر دهد:
document.getElementById('box').style.width = '200px';
مرورگر باید اندازه جدید را محاسبه کند
موقعیت عناصر دیگر نیز ممکن است تغییر کند
این همان Reflow است
💡 به زبان ساده:
Reflow یعنی مرورگر همه چیز را دوباره اندازهگیری میکند و تصمیم میگیرد چه چیزی کجا قرار گیرد.
Repaint زمانی اتفاق میافتد که ظاهر یک عنصر تغییر کند ولی موقعیت آن ثابت بماند.
color
background-color
border-color
visibility: hidden / visible
💡 توجه: این تغییرات باعث Reflow نمیشوند، فقط مرورگر آن عنصر را دوباره رنگآمیزی یا رسم میکند.
document.getElementById('box').style.backgroundColor = 'red';
اندازه یا موقعیت div تغییر نکرده
فقط رنگ آن تغییر کرده
مرورگر عنصر را دوباره Paint میکند
Reflow انجام نمیشود
💡 به زبان ساده:
Repaint یعنی مرورگر رنگ و ظاهر را دوباره روی همان محل رسم میکند.
یک مفهوم CSS است که تعیین میکند کدام عناصر روی صفحه روی هم قرار میگیرند و ترتیب نمایش آنها چگونه است.
به زبان ساده:
Stacking Context مثل یک لایه یا گروه است که عناصر داخل آن نسبت به هم ترتیب میگیرند، اما این ترتیب فقط درون همان گروه معتبر است و روی عناصر خارج از آن تاثیری ندارد.
وقتی چند عنصر روی هم قرار میگیرند، مرورگر باید تصمیم بگیرد:
کدام عنصر جلوتر باشد
کدام عنصر پشت سر دیگری قرار گیرد
Stacking Context این کار را بهصورت منظم انجام میدهد و از سردرگمی جلوگیری میکند.
یک عنصر زمانی Stacking Context میسازد که یکی از این شرایط را داشته باشد:
position غیر static + z-index متفاوت از auto
opacity کمتر از ۱
transform یا filter یا perspective
isolation: isolate
برخی ویژگیهای CSS مثل mix-blend-mode یا will-change
فرض کنید سه div داریم:
<div class="parent"> <div class="child1">A</div> <div class="child2">B</div> </div> <div class="outside">C</div>
.parent { position: relative; z-index: 10; /* ایجاد Stacking Context */ } .child1 { z-index: 5; } .child2 { z-index: 15; } .outside { z-index: 20; }
.parent یک Stacking Context جدید ساخته است.
داخل .parent، .child1 و .child2 نسبت به هم مرتب میشوند (child2 جلوتر).
اما .outside که خارج از .parent است، نمیتواند صرفاً با z-index 20 نسبت به .child2 جلوتر یا عقبتر قرار بگیرد چون child2 داخل Stacking Context دیگری است.
در واقع Stacking Context مانند یک صفحه شیشهای مستقل است:
عناصر داخل آن ترتیب خودشان را دارند
عناصر بیرون نمیتوانند آن ترتیب را تحت تأثیر قرار دهند
به همین دلیل وقتی z-index بالا روی یک عنصر اعمال میکنید ولی نتیجه نمیگیرید، معمولاً به دلیل Stacking Context والد است.
در این مقاله دیدیم که Rendering در مرورگر یک خط تولید منظم است:
Parse HTML → DOM
Parse CSS → CSSOM
Render Tree
Layout (Reflow)
Paint
Composition
و یاد گرفتیم:
flex/grid در مرحله Layout اثر میگذارند
responsive هنگام Layout اتفاق میافتد
تغییر اندازه مرورگر Reflow را فعال میکند
z-index و stacking context در مرحله Paint تصمیمگیری میشوند
ترکیب نهایی لایهها در Compositor انجام میشود
در مقاله بعدی خواهیم دید مرحله اول چگونه انجام میشود و مرورگر چه مکانیزم هایی برای تولید DOM Tree دارد ؟