حل معمای اندازه واقعی جعبه: box-sizing

در درس قبل به این نکته اشاره کردیم که width و height، به‌طور پیش‌فرض فقط ناحیه Content رو تعیین می‌کنن؛ نه Padding و نه Border. این رفتار می‌تونه محاسبه اندازه نهایی یک عنصر رو کمی پیچیده کنه. خوشبختانه CSS یک Property به اسم box-sizing داره که کنترل کاملی روی این رفتار به ما می‌ده.

مشکلی که box-sizing حل می‌کند

.box {
  width: 300px;
  padding: 20px;
  border: 5px solid teal;
}

خیلی‌ها فکر می‌کنن عرض نهایی این جعبه ۳۰۰ پیکسله. اما در حالت پیش‌فرض CSS، عرض واقعی و کامل این جعبه این‌طور محاسبه می‌شه:

عرض نهایی = width + padding چپ و راست + border چپ و راست
عرض نهایی = 300 + (20 + 20) + (5 + 5) = 350px

یعنی جعبه واقعی، ۵۰ پیکسل بزرگ‌تر از چیزیه که در نگاه اول انتظارش رو داشتیم. این رفتار، دقیقاً همون چیزیه که مقدار پیش‌فرض box-sizing یعنی content-box ایجاد می‌کنه.

content-box: مقدار پیش‌فرض

.box {
  box-sizing: content-box;
  width: 300px;
  padding: 20px;
  border: 5px solid teal;
}

در حالت content-box (که مقدار پیش‌فرض همه عناصره، حتی وقتی این خط رو ننویسیم)، Propertyهای width و height فقط ناحیه Content رو مشخص می‌کنن؛ Padding و Border همیشه اضافه بر این مقدار محاسبه می‌شن.

border-box: راه‌حل مدرن و رایج

.box {
  box-sizing: border-box;
  width: 300px;
  padding: 20px;
  border: 5px solid teal;
}

در حالت border-box، مقدار width دیگه فقط مربوط به Content نیست؛ بلکه کل عرض جعبه (شامل Content، Padding و Border) رو مشخص می‌کنه. یعنی در این مثال، عرض نهایی جعبه دقیقاً همون ۳۰۰ پیکسل خواهد بود؛ مرورگر خودش به‌طور خودکار Padding و Border رو از داخل همین ۳۰۰ پیکسل کم می‌کنه تا فضای Content به‌درستی محاسبه بشه.

عرض Content در حالت border-box = 300 - (20 + 20) - (5 + 5) = 250px

مقایسه دو حالت در یک جدول

ویژگی content-box (پیش‌فرض) border-box
width شامل چه چیزی است فقط Content Content + Padding + Border
Padding و Border اضافه بر width تعریف‌شده از داخل width تعریف‌شده کم می‌شوند
پیش‌بینی اندازه نهایی نیاز به محاسبه دستی مستقیم و ساده

چرا border-box در پروژه‌های واقعی محبوب‌تر است؟

وقتی از border-box استفاده می‌کنیم، اگه بعداً بخوایم Padding یا Border یک عنصر رو تغییر بدیم، عرض نهایی جعبه ثابت می‌مونه؛ فقط فضای داخلی Content کمی تغییر می‌کنه. این پیش‌بینی‌پذیری، کار طراحی چیدمان‌های پیچیده (مخصوصاً با Flexbox و Grid که در فصل‌های بعدی می‌بینیم) رو خیلی ساده‌تر می‌کنه.

تکنیک رایج: اعمال border-box روی کل صفحه

به‌خاطر همین مزیت، یکی از رایج‌ترین الگوهای اول هر پروژه CSS، اعمال border-box روی تمام عناصر صفحه با کمک Universal Selector‌ه:

*,
*::before,
*::after {
  box-sizing: border-box;
}

این Rule باعث می‌شه تمام عناصر (و همچنین Pseudo-elementهای ::before و ::after) به‌طور پیش‌فرض از border-box استفاده کنن، نه content-box. این کار محاسبه اندازه‌ها رو در کل پروژه بسیار ساده‌تر و قابل‌پیش‌بینی‌تر می‌کنه.

یک مثال مقایسه‌ای کامل

.content-box-example {
  box-sizing: content-box;
  width: 200px;
  padding: 15px;
  border: 3px solid coral;
}

.border-box-example {
  box-sizing: border-box;
  width: 200px;
  padding: 15px;
  border: 3px solid coral;
}
<div class="content-box-example">این جعبه در واقع ۲۳۶ پیکسل عرض دارد.</div>
<div class="border-box-example">این جعبه دقیقاً ۲۰۰ پیکسل عرض دارد.</div>

هر دو جعبه، مقدار width: 200px یکسانی دارن. اما چون اولی content-box است، عرض واقعی‌ش 200 + (15+15) + (3+3) = 236px می‌شه. دومی چون border-box است، عرض واقعی‌ش دقیقاً همون ۲۰۰ پیکسل باقی می‌مونه؛ فقط فضای داخلی Content به‌طور خودکار کوچک‌تر محاسبه می‌شه.

نکات مهم

  • مقدار پیش‌فرض box-sizing در تمام مرورگرها، content-box است.
  • در content-box، اندازه نهایی جعبه همیشه بزرگ‌تر از width تعریف‌شده خواهد بود (به‌اندازه Padding و Border).
  • در border-box، اندازه width همیشه ثابت می‌ماند و Padding و Border از داخل همان فضا کم می‌شوند.

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

  • فراموش کردن تفاوت content-box و border-box، که باعث می‌شه عرض یا ارتفاع واقعی عناصر با انتظار طراح مطابقت نداشته باشه.
  • اضافه کردن Padding یا Border به یک عنصر با box-sizing پیش‌فرض (content-box)، بدون در نظر گرفتن این‌که این مقادیر به عرض نهایی اضافه می‌شن.
  • فراموش کردن اعمال border-box به‌صورت全域 (Universal) در ابتدای پروژه، که باعث محاسبات دستی و پیچیده در ادامه کار می‌شه.

بهترین روش‌ها

  • در اکثر پروژه‌های واقعی، از همون ابتدا Universal Selector رو برای اعمال box-sizing: border-box روی کل صفحه استفاده کن.
  • همیشه قبل از تعریف width یک عنصر که Padding یا Border هم داره، مطمئن شو کدوم حالت box-sizing فعاله.

جمع‌بندی

Property به اسم box-sizing مشخص می‌کنه که width و height یک عنصر، دقیقاً شامل چه بخش‌هایی از جعبه می‌شن. در حالت پیش‌فرض (content-box)، این مقادیر فقط Content رو تعیین می‌کنن و Padding و Border اضافه بر اون محاسبه می‌شن. در حالت border-box، مقدار width شامل Content، Padding و Border با هم می‌شه؛ که باعث پیش‌بینی‌پذیری بیشتر در طراحی می‌شه و به همین دلیل در اکثر پروژه‌های واقعی ترجیح داده می‌شه.