خروج کامل از جریان طبیعی: absolute و Containing Block

در درس قبل با relative آشنا شدیم که عنصر رو نسبت به جایگاه اصلی خودش جابه‌جا می‌کنه، بدون خارج شدن از Normal Flow. حالا وقتشه با absolute آشنا بشیم؛ مقداری که رفتار کاملاً متفاوتی داره و عنصر رو به‌طور کامل از جریان طبیعی صفحه خارج می‌کنه.

position: absolute چیست؟

.box {
  position: absolute;
  top: 20px;
  left: 30px;
}

وقتی position: absolute تعریف بشه، عنصر کاملاً از Normal Flow خارج می‌شه؛ یعنی نه‌تنها هیچ فضایی در چیدمان طبیعی اشغال نمی‌کنه (دقیقاً مثل display: none که در فصل ۵ دیدیم، از این نظر که فضایی باقی نمی‌ذاره)، بلکه موقعیتش هم دیگه به جایگاه طبیعی خودش در HTML وابسته نیست؛ بلکه دقیقاً بر اساس مقادیر top، right، bottom و left، نسبت به یک عنصر مرجع دیگه، محاسبه می‌شه.

تفاوت کلیدی با relative: فضای اصلی حفظ نمی‌شود

.box {
  position: absolute;
  top: 0;
  right: 0;
}
<div>جعبه اول</div>
<div class="box">جعبه دوم (absolute)</div>
<div>جعبه سوم</div>

برخلاف relative که فضای اصلی عنصر رو محفوظ نگه می‌داشت، در حالت absolute، عنصر کاملاً از جریان چیدمان خارج می‌شه؛ یعنی «جعبه اول» و «جعبه سوم» طوری رفتار می‌کنن که انگار «جعبه دوم» اصلاً وجود نداره، و مستقیماً کنار هم قرار می‌گیرن. «جعبه دوم» به‌طور کاملاً مستقل، بر اساس مقادیر Offset، جای دیگه‌ای از صفحه (نسبت به یک مرجع خاص) قرار می‌گیره.

Containing Block چیست؟

حالا سؤال اصلی اینه: وقتی می‌گیم عنصر absolute نسبت به top: 0 و right: 0 قرار می‌گیره، این مقادیر دقیقاً نسبت به چی محاسبه می‌شن؟ جواب این سؤال، مفهومی به اسم Containing Block است؛ یعنی نزدیک‌ترین عنصر جد (Ancestor) که مقدار position‌ش چیزی غیر از static باشه (یعنی relative، absolute، fixed یا sticky).

قانون طلایی: absolute دنبال نزدیک‌ترین جد positioned می‌گردد

.parent {
  position: relative;
  width: 400px;
  height: 300px;
}

.child {
  position: absolute;
  top: 10px;
  right: 10px;
}
<div class="parent">
  <div class="child">گوشه بالا-راست</div>
</div>

در این مثال، چون .parent مقدار position: relative داره (که در درس قبل دیدیم، حتی بدون هیچ Offsetای هم می‌تونه این نقش رو ایفا کنه)، این عنصر به‌عنوان Containing Block فرزندش (.child) عمل می‌کنه. یعنی top: 10px و right: 10px، دقیقاً نسبت به گوشه‌های .parent محاسبه می‌شن؛ نتیجه این می‌شه که .child دقیقاً در گوشه بالا-راست .parent قرار می‌گیره.

چه اتفاقی می‌افتد اگر هیچ جد Positioned‌ای وجود نداشته باشد؟

.child {
  position: absolute;
  top: 10px;
  right: 10px;
}
<div>
  <div class="child">این المان کجا قرار می‌گیرد؟</div>
</div>

اگه هیچ‌کدوم از عناصر جد (تا بالاترین سطح ممکن)، مقدار position‌شون چیزی غیر از static نباشه، مرورگر به‌طور خودکار به سراغ Initial Containing Block می‌ره؛ که معمولاً معادل کل صفحه (یعنی نسبت به viewport یا عنصر html) در نظر گرفته می‌شه. در این مثال، چون هیچ جد relativeای وجود نداره، .child نسبت به کل صفحه، در فاصله ۱۰ پیکسلی از بالا و ۱۰ پیکسلی از راست قرار می‌گیره؛ نه نسبت به div والدش.

چرا این نکته اهمیت عملی زیادی دارد؟

این دقیقاً همون دلیلیه که در درس قبل گفتیم، یکی از رایج‌ترین کاربردهای position: relative، تعریفش روی یک عنصر والد، فقط به‌خاطر ایجاد یک Containing Block برای فرزندان absoluteه؛ حتی اگه خود اون عنصر والد، هیچ Offset خاصی نداشته باشه. بدون این کار، عناصر absolute ممکنه به‌جای موقعیت‌گیری نسبت به والد نزدیک‌شون، نسبت به کل صفحه جابه‌جا بشن؛ که معمولاً نتیجه دلخواه ما نیست.

یک کاربرد بسیار رایج: نشان (Badge) روی یک کارت

.product-card {
  position: relative;
  width: 250px;
  padding: 16px;
}

.badge {
  position: absolute;
  top: -10px;
  right: -10px;
  background-color: crimson;
  color: white;
  padding: 4px 10px;
  border-radius: 12px;
}
<div class="product-card">
  <span class="badge">جدید</span>
  <p>توضیحات محصول</p>
</div>

در این مثال، .badge دقیقاً روی گوشه بالا-راست کارت (حتی کمی بیرون از لبه‌های اون، به‌خاطر مقادیر منفی) قرار می‌گیره؛ چون .product-card مقدار position: relative داره و به‌عنوان Containing Block عمل می‌کنه. این الگو، یکی از رایج‌ترین روش‌ها برای نمایش نشان‌های کوچک (مثل «جدید» یا «تخفیف») روی کارت‌های محصول در طراحی رابط کاربریه.

عناصر absolute از Normal Flow مستقل هستند

.container {
  position: relative;
}

.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

یک کاربرد رایج دیگه، ساخت یک لایه Overlay که کل فضای والدش رو می‌پوشونه؛ با تنظیم هر چهار مقدار Offset (top: 0، right: 0، bottom: 0، left: 0) یا ترکیب top: 0; left: 0; با width: 100%; height: 100%;، می‌شه یک عنصر رو دقیقاً هم‌اندازه والدش کرد، بدون توجه به محتوای واقعی داخلش.

نکات مهم

  • position: absolute عنصر را کاملاً از Normal Flow خارج می‌کند و هیچ فضایی در چیدمان اشغال نمی‌کند.
  • مقادیر top، right، bottom و left، نسبت به نزدیک‌ترین Containing Block (یعنی نزدیک‌ترین جد با position غیر از static) محاسبه می‌شوند.
  • اگر هیچ جد Positioned‌ای وجود نداشته باشد، عنصر absolute نسبت به کل صفحه (Initial Containing Block) موقعیت‌دهی می‌شود.

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

  • فراموش کردن تعریف position: relative روی والد مورد نظر، که باعث می‌شود عنصر absolute به‌جای والد، نسبت به کل صفحه جابه‌جا شود.
  • تصور اینکه absolute دقیقاً مثل relative رفتار می‌کند و فضای اصلی خودش را حفظ می‌کند؛ در حالی که کاملاً از Flow خارج می‌شود.
  • عدم توجه به این‌که هر عنصر با position غیر از static (نه فقط relative)، می‌تواند به‌عنوان Containing Block عمل کند.

جمع‌بندی

position: absolute عنصر را کاملاً از Normal Flow خارج می‌کند و موقعیتش را بر اساس مقادیر top، right، bottom و left، نسبت به نزدیک‌ترین Containing Block محاسبه می‌کند. Containing Block، نزدیک‌ترین عنصر جد با position غیر از static است؛ در نبود چنین جدی، عنصر نسبت به کل صفحه موقعیت‌دهی می‌شود. به همین دلیل، تعریف position: relative روی والد مورد نظر (حتی بدون هیچ Offset خاصی)، یکی از رایج‌ترین و مهم‌ترین الگوهای کار با absolute محسوب می‌شود.