وقتی دو Margin در هم ادغام می‌شوند: Margin Collapse

تا اینجا فکر می‌کردیم Margin همیشه رفتاری کاملاً قابل‌پیش‌بینی داره: هر مقداری که تعریف کنیم، دقیقاً همون فاصله ایجاد می‌شه. اما یک رفتار خاص و گاهی گیج‌کننده در CSS وجود داره به اسم Margin Collapse که این فرض رو زیر سؤال می‌بره. بیایم دقیق ببینیم این پدیده چیه و کِی اتفاق می‌افته.

Margin Collapse چیست؟

Margin Collapse (ادغام حاشیه) به رفتاری گفته می‌شه که طی اون، Margin عمودی (بالا یا پایین) دو عنصر مجاور، به‌جای اینکه با هم جمع بشن، در هم ادغام می‌شن و فقط بزرگ‌ترین مقدار باقی می‌مونه.

مثال ساده: دو عنصر Sibling

.box-one {
  margin-bottom: 30px;
}

.box-two {
  margin-top: 20px;
}
<div class="box-one">جعبه اول</div>
<div class="box-two">جعبه دوم</div>

فکر منطقی این‌طوره که فاصله بین این دو جعبه باید برابر مجموع ۳۰ و ۲۰ پیکسل، یعنی ۵۰ پیکسل باشه. اما نتیجه واقعی این‌طور نیست؛ فاصله نهایی فقط ۳۰ پیکسل خواهد بود؛ یعنی بزرگ‌ترین مقدار بین این دو Margin، نه مجموع‌شون.

چرا این اتفاق می‌افتد؟

این رفتار عمداً در طراحی CSS گنجونده شده تا فاصله‌گذاری بین بلوک‌های متنی (مثل پاراگراف‌ها) طبیعی‌تر به‌نظر برسه. اگه Marginها همیشه با هم جمع می‌شدن، هر پاراگراف پشت سرهم باعث فاصله‌های بزرگ‌تر و بزرگ‌تری می‌شد که از نظر بصری خوشایند نبود.

Margin Collapse فقط بین والد و فرزند هم اتفاق می‌افتد

این پدیده فقط بین دو Sibling رخ نمی‌ده؛ بلکه بین یک عنصر والد و اولین یا آخرین فرزندش هم می‌تونه اتفاق بیفته، به شرطی که هیچ Padding، Border یا محتوایی بین اون دو فاصله نینداخته باشه.

.parent {
  margin-top: 40px;
  background-color: #f5f5f5;
}

.child {
  margin-top: 60px;
}
<div class="parent">
  <p class="child">این پاراگراف است.</p>
</div>

ممکنه فکر کنیم فاصله بالای .parent از عنصر قبلی‌ش، ۴۰ پیکسله. اما چون هیچ Padding یا Borderای بین .parent و .child وجود نداره، Margin بزرگ‌تر (۶۰ پیکسل) از فرزند، عملاً به بیرون از والد «نشت» می‌کنه و با Margin والد ادغام می‌شه. نتیجه نهایی، فاصله ۶۰ پیکسلی خواهد بود؛ نه ۴۰ و نه مجموع این دو.

چه چیزی مانع Margin Collapse بین والد و فرزند می‌شود؟

اگه هر یک از موارد زیر بین والد و فرزند وجود داشته باشه، Margin Collapse دیگه اتفاق نمی‌افته:

  • وجود padding روی والد (حتی مقدار کم)
  • وجود border روی والد
  • وجود محتوای دیگه (مثلاً متن) قبل از فرزند، داخل والد
  • تنظیم overflow غیر از visible روی والد (که این مفهوم رو در درس‌های آینده کامل می‌بینیم)
.parent {
  margin-top: 40px;
  padding-top: 1px;
  background-color: #f5f5f5;
}

.child {
  margin-top: 60px;
}

با اضافه شدن حتی یک پیکسل padding-top به والد، دیگه Margin Collapse اتفاق نمی‌افته؛ چون این padding یه لایه فیزیکی بین Margin والد و Margin فرزند ایجاد می‌کنه. حالا فاصله والد از عنصر قبلی‌ش دقیقاً همون ۴۰ پیکسل خواهد بود، و فرزند هم به‌طور جدا ۶۰ پیکسل از بالای والدش (که حالا padding داره) فاصله می‌گیره.

Margin Collapse در جعبه‌های خالی

یه حالت خاص دیگه: اگه یک عنصر خالی باشه (بدون Content، Padding و Border) و هم margin-top و هم margin-bottom داشته باشه، این دو مقدار هم می‌تونن با هم ادغام بشن:

.empty-box {
  margin-top: 20px;
  margin-bottom: 40px;
}
<div class="empty-box"></div>

چون این جعبه کاملاً خالیه و هیچ Padding یا Borderای هم نداره، مقدار margin-top و margin-bottom با هم ادغام می‌شن و فقط بزرگ‌ترین مقدار (۴۰ پیکسل) به‌عنوان فاصله کلی این جعبه از بالا و پایین باقی می‌مونه.

چه زمانی Margin Collapse اتفاق نمی‌افتد؟

چند مورد مهم که باید بدونی Margin Collapse در اون‌ها رخ نمی‌ده:

  • Margin افقی (چپ و راست) هیچ‌وقت ادغام نمی‌شه؛ این پدیده فقط مخصوص Margin عمودیه (بالا و پایین).
  • وقتی عناصر داخل یک Flex Container یا Grid Container قرار دارن (این مفاهیم رو در فصل‌های آینده کامل می‌بینیم)، اصلاً Margin Collapse اتفاق نمی‌افته.
  • اگه بین دو عنصر Sibling، حتی یک عنصر دیگه (با هر Displayای) با Content واقعی وجود داشته باشه، دیگه ادغام مستقیم رخ نمی‌ده.

یک مثال کامل برای جمع‌بندی

h2 {
  margin-bottom: 20px;
}

p {
  margin-top: 15px;
  margin-bottom: 15px;
}
<h2>عنوان بخش</h2>
<p>پاراگراف اول</p>
<p>پاراگراف دوم</p>

فاصله بین h2 و پاراگراف اول، به‌جای ۳۵ پیکسل (یعنی ۲۰ + ۱۵)، برابر با ۲۰ پیکسل خواهد بود؛ چون بزرگ‌ترین مقدار بین این دو Margin برنده می‌شه. فاصله بین دو پاراگراف هم، به‌جای ۳۰ پیکسل (۱۵ + ۱۵)، همچنان ۱۵ پیکسل باقی می‌مونه؛ چون هر دو مقدار برابرن و ادغام اون‌ها همون مقدار مساوی رو نتیجه می‌ده.

نکات مهم

  • Margin Collapse فقط برای Margin عمودی (بالا و پایین) اتفاق می‌افته، نه افقی.
  • این پدیده هم بین دو Sibling، و هم بین یک والد و اولین یا آخرین فرزندش (در نبود Padding، Border یا Content میانی) رخ می‌ده.
  • وجود حتی مقدار کمی Padding یا Border روی والد، مانع نشت Margin فرزند به بیرون می‌شه.

اشتباهات رایج

  • تصور اینکه فاصله نهایی بین دو عنصر، همیشه برابر مجموع Marginهاشونه؛ در حالی که در بسیاری موارد، فقط بزرگ‌ترین مقدار اعمال می‌شه.
  • غافل شدن از نشت Margin فرزند به بیرون از والد، وقتی هیچ Padding یا Borderای روی والد تعریف نشده.
  • تلاش برای دیباگ یک فاصله «غیرمنتظره» بدون در نظر گرفتن احتمال وقوع Margin Collapse.

جمع‌بندی

Margin Collapse رفتاری‌ست که طی آن، Margin عمودی دو عنصر مجاور (یا والد و فرزندش در شرایط خاص)، به‌جای جمع شدن، در هم ادغام می‌شود و فقط بزرگ‌ترین مقدار باقی می‌ماند. این پدیده تنها مخصوص Margin عمودی است، در Flexbox و Grid رخ نمی‌دهد، و با اضافه کردن Padding یا Border به والد قابل جلوگیری است. درک این رفتار برای دیباگ کردن فاصله‌های غیرمنتظره در CSS ضروری است.