Box Model یک مفهوم بسیار مهم و کلیدی در CSS است که به رفتار عناصر از نظر قرارگیری در صفحه
و فضای اشغالشده
توسط باکسها مربوط است. برای درک مفهوم Box Model لازم است که ابتدا با برخی از مفاهیم و پراپرتیهای مربوط به
این موضوع آشنا شوبم. قبل از هر چیز، با باکسهای Block و Inline و تفاوت
بین آنها آشنا میشویم. سپس، در مورد
ابعاد عناصر و پراپرتیهای width و height صحبت میکنیم. بعد از آن، با
مفاهیم Margin و Padding و پراپرتیهای
مربوط به آنها آشنا میشویم و بالاخره با بررسی دقیقتر تفاوت بین باکسهای Inline و Block پازل مربوط به مفهوم
Box Model کامل میشود و میتوانیم به یک تفسیر جامع از این مفهوم دست پیدا کنیم.
باکسهای Inline و Block
همانطور که در درس قبل هم اشاره شد، عناصر HTML معادل باکسهای CSS هستند. یعنی CSS هر عنصر موجود در صفحه را به
صورت یک باکس مستطیلی رندر میکند. باکسِ یک عنصر یا Inline است یا Block و این موضوعی است که از روی مقدار
پیشفرض یک پراپرتی با نام display مشخص میشود. یعنی هر عنصری که مقدار پیشفرض پراپرتی
display برای آن برابر
با inline باشد، یک عنصر Inline است و هر عنصری که مقدار پیشفرض پراپرتی display برای آن
برابر با block باشد،
یک عنصر Block است.
به طور خلاصه، تفاوت باکسهای Inline و Block از این قرار است:
عناصر یا باکسهای Block همیشه در یک خط یا سطر جدید قرار میگیرند و کل عرض آن سطر (عرض عنصر والد) را اشغال
میکنند و هر عنصری که بعد از یک باکس Block بیاید، باید در سطر یا خط بعدی قرار گیرد. اما عناصر یا باکسهای
inline لزوماً از یک خط جدید شروع نمیشوند و از فضای موجود در سطر جاری، تنها به اندازهی محتوای خود اشغال
میکنند.
تفاوت عناصر Block و Inline
بنابراین، عناصری مانند پاراگرافها (p)، هدینگها (h1, …, h6)، جداول (table) و div که همواره از یک خط جدید
شروع شده و فارغ از محتوای خود، کل عرض عنصر والد خود را اشغال میکنند، باکسها یا عناصر Block هستند و عناصری
مانند لینکها (a)، تصاویر (img) و span که تنها به اندازهی محتوای خود از فضای خط جاری را اشغال میکنند و از
یک خط جدید نیز شروع نمیشوند، عناصر یا باکسهای Inline هستند. اجازه دهید با ارائهی یک مثال، تفاوت باکسهای
Block و Inline را در عمل ببینیم. در کد زیر، فریم عناصر Inline با رنگ سبز و فریم عناصر Block با رنگ قرمز
نمایش داده میشود:
همانطور که میبینید، باکسهای عناصر Block یعنی h1، h2 و p از ابتدا تا انتهای یک سطر یا به عبارت
دیگر، صد
درصد عرض سطر جاری را اشغال میکنند و ارتفاع این باکسها نیز بر حسب محتوا تنظیم میشود. اما عناصر Inline این
مثال یعنی a، span و strong تنها به اندازهی محتوای خود از عرض و ارتفاع ممکن، فضا میگیرند.
نکتهی مهم در ارتباط با باکسهای Inline و Block این است که Box Model روی این دو گروه از عناصر، معنای متفاوتی
دارد و به دو شکل متفاوت تفسیر میشود.
تبدیل باکسهای Block و Inline به یکدیگر
همانطور که در بالا اشاره شد، این پراپرتی display است که Block یا Inline بودن یک عنصر را
مشخص میکند. پس، با
تغیییر مقدار پیشفرض پراپرتی display برای یک عنصر، میتوان عناصر Block و Inline را به
یکدیگر تبدیل کرد.
میدانیم که عنصر li از نوع Block است و به همین دلیل است که هر یک از آیتمهای یک لیست در یک خط مجزا نمایش
داده میشوند. مثال زیر را ببینید:
CSS
ul li{list-style-type: none;}
اما اگر مقدار پراپرتی display را برای عنصر li تغییر داده و آن را روی inline تنظیم کنیم،
آیتمها مانند عناصر
Inline در کنار یکدیگر نمایش داده میشوند و فقط زمانی یک آیتم در یک خط جدید نمایش داده میشود که فضای کافی
برای نمایش آن آیتم در خط قبلی وجود نداشته باشد. مثال زیر را ببینید:
CSS
ul li{list-style-type: none;display: inline;}
تعیین ابعاد باکسها
منظور از ابعاد باکس، عرض و ارتفاع آن است که چند پراپرتی برای تعیین آنها وجود دارد که مهمترین آنها width و
height هستند. البته باید توجه داشته باشید که این پراپرتیها تنها روی عناصر Block اعمال
میشوند و بهکارگیری
آنها روی عناصر Inline هیچ نتیجهای ندارد و یک عنصر Inline در هر شرایطی، تنها به اندازهی محتوای خود از عرض
صفحه یا عنصر والد را اشغال میکند.
عناصر Block در حالت پیشفرض، کل عرض عنصر والد خود را اشغال میکنند. به عبارت دیگر، مقدار پراپرتی width برای
این عناصر برابر با 100% است. ارتفاع این عناصر نیز از روی محتوای آنها تعیین میشود که این به این
معناست که
مقدار پیشفرض پراپرتی height برای عناصر Block برابر با auto است. برای تعیین مقدار دلخواه
به عنوان عرض و
ارتفاع عنصر، باید مقادیر مورد نظر را به پراپرتیهای width و height
اختصاص دهیم.
CSS
#child{height: 50%;width: 75%;}
جداقل و حداکثر ابعاد
علاوه بر تخصیص یک سایز ثابت و مشخص به یک عنصر، امکان تعیین حداقل یا حداکثر عرض و ارتفاع نیز برای عنصر وجود
دارد. اگر باکسی داشته باشیم که محتوای آن متغیر باشد و بخواهیم آن باکس همیشه دارای یک ارتفاع حداقلی باشد، می
توانیم از پراپرتی min-height بدین منظور استفاده کنیم. در این صورت، باکس مورد نظر دارای
آن ارتفاع کمینه خواهد
بود و با افزایش احتمالی محتوا، مقدار ارتفاع باکس نیز افزایش مییابد تا بتواند محتوا را در بر گیرد.
در مثال زیر، دو باکس داریم که ارتفاع حداقل برای هر دوی آنها روی 100px تنظیم شده است. باکس اول با وجودی
که محتوایی ندارد، با ارتفاع 100px نمایش داده میشود؛ چون این مقداری است که ما به عنوان حداقل ارتفاع تعیین
کردهایم. اما باکس سمت راست محتوایی دارد که ارتفاع 100px جوابگوی ان نیست و لذا ارتفاع به میزان لازم افزایش
مییابد.
این روش برای مواردی که مقدار محتوای درون یک باکس متغیر است، مفید بوده و مانع از بروز سرریز محتوا میشود.
پراپرتی max-width نیز کاربرد خاص خودش را دارد و در مواردی که بخواهیم ترتیبی دهیم که عرض
باکس یک عنصر هرگز از
یک مقدار مشخصی بیشتر نشود، میتوانیم از آن استفاده کنیم. به عنوان یک مثال از کاربرد پراپرتی max-with فرض
کنید پراپرتی width را برای یک عکس روی مقدار 100% تنظیم کنیم و عرض طبیعی عکس
از عرض باکس کانتینرش کمتر باشد.
در این صورت، عکس مورد نظر اجباراً کشیدهتر شده و بزرگتر میشود و این امر میتواند باعث افت کیفیت عکس بشود.
اما اگر به جای width از پراپرتی max-width استفاده کنیم، این مشکل رخ
نمیدهد.
مفاهیم Padding و Margin
یکی دیگر از مؤلفههایی که برای درک مفهوم Box Model و محاسبهی فضای اشغالشده توسط عناصر باید با آن آشنا
شویم، مفاهیم Margin و Padding هستند. منظور از Margin فاصله یا حاشیهای است که بین یک عنصر و عناصر مجاورش
وجود دارد و Padding فاصلهی بین محتوا و فریم (border) عنصر است. در این بخش، با پراپرتیهای تنظیمکنندهی
Margin و Padding آشنا میشویم.
مفهوم Padding و پراپرتیهای مربوط به آن
فاصلهی بین محتوای یک عنصر و فریم (border) آن را Padding میگوییم و این فاصله را میتوان با استفاده از
پراپرتیهای padding-top، padding-right، padding-bottom و padding-left از چهار طرف تعیین کرد. البته یک
پراپرتی اختصاری با نام padding نیز وجود دارد که امکان تنظیم هر چهار پراپرتی مذکور را در
قالب تنها یک دستور
فراهم میکند. مقدار این پراپرتیها میتواند یک مقدار طولی نامنفی باشد و یا یک مقدار بر حسب درصد که نسبت به
عرض محتوا یعنی مقدار پراپرتی width سنجیده میشود. مثال زیر را ببینید:
اما همانطور که گفتیم، به جای این پراپرتیها میتوانیم از پراپرتی اختصاری padding برای
تنظیم همزمان Padding
از چهار طرف عنصر، استفاده کنیم. این پراپرتی میتواند از یک تا چهار مقدار را دریافت کند:
تخصیص یک مقدار به پراپرتی padding به این معناست که آن مقدار برای میزان Padding از هر
چهار طرف عنصر در
نظر گرفته شود.
تخصیص دو مقدار به پراپرتی padding به این معناست که مقدار اول برای Padding از بالا و
پایین یعنی
پراپرتیهای padding-top و padding-bottom در نظر گرفته شود و مقدار
دوم برای Padding از راست و چپ یعنی
پراپرتیهای padding-right و padding-left.
تخصیص سه مقدار به پراپرتی padding به این معناست که مقدار اول برای padding-top و مقدار دوم برای
padding-right و padding-left و مقدار سوم برای padding-bottom در نظر گرفته شود.
تخصیص چهار مقدار به پراپرتی padding به این معناست که مقادیر بهترتیب برای Padding از
بالا، راست، پایین و
چپ در نظر گرفته شوند.
مثال بالا را میتوانیم با استفاده از پراپرتی اختصاری padding به صورت زیر بازنویسی کنیم:
مفهوم Margin بیانگر فضای اطراف باکس عنصر است. این فضا باعث میشود که یک حاشیه برای عنصر مورد نظر ایجاد شود و
لذا سایر عناصر از این عنصر فاصله بگیرند. بر خلاف پراپرتیهای مربوط به Padding که تنها قادر به دریافت مقادیر
نامنفی هستند، پراپرتیهای مربوط به Margin میتواند مقادیر مثبت یا منفی را دریافت کنند. تعیین اعداد منفی به
عنوان مقدار این پراپرتیها میتواند باعث ایجاد تداخل (overlap) بین عنصر با سایر عناصر و محتوای صفحه شود.
برای تنظیم مقدار Margin برای یک عنصر، میتوانیم از پراپرتیهای margin-top، margin-right، margin-bottom و
margin-left برای تنظیم میزان Margin از چهار جهت استفاده کنیم. این پراپرتیها میتوانند
یک مقدار طولی، یک
مقدار بر حسب درصد و یا مقدار auto را دریافت کنند. مقادیر درصدی نسبت به عرض عنصر والد یا کانتینر سنجیده
میشوند.
اگر بخواهیم یک عنصر را در مرکز صفحه یا به طور کلی در مرکز عنصر والد خود قرار دهیم، میتوانیم مقدار
پراپرتیهای margin-left و margin-right را برابر با auto قرار دهیم.
مثال زیر را ببینید:
برای درک کامل مفهوم Margin باید با مفهومی به نام Margin Collapsing آشنا باشیم. این مفوم بیان میکند که اگر
حاشیههای تعیین شده برای دو عنصر با استفاده از پراپرتیهای مربوط به Margin به گونهای باشد که این حاشیهها
با هم تماس
داشته باشند، دو حاشیه با هم ترکیب شده و یک مقدار که مقدار حاشیهی بزرگتر است، بدست میآید. البته این به شرطی
است که مقدار Margin برای هر دو عنصر مثبت باشد اما اگر لااقل یکی از آنها دارای مقدار منفی باشد، مقدار منفی از
کل کم میشود.
در مثال زیر، دو پاراگراف داریم. مقدار Margin برای پاراگراف اول برابر با 50px و برای پاراگراف دوم برابر با
30px است. همانطور که میبینید، دو مقدار با هم ادغام شده و مقدار بزرگتر یعنی 50px به عنوان فاصلهی بین دو
عنصر تعیین شده و نه مجموع آنها.
CSS
.one{margin-bottom: 50px;}.two{margin-top: 30px;}
عناصر یا باکسهای inline-block
مقادیر block و inline تنها مقادیر قابل تخصیص به پراپرتی display نیستند و مقادیر متعدد
دیگری وجود دارد که
میتوان به این پراپرتی اختصاص داد. در اینجا قصد داریم به یک مقدار خاص اشاره کنیم که با اعطای آن به display
میتوانیم حالت بینابینی از مقادیر block و inline برای عنصر ایجاد کنیم؛ یعنی عنصر از برخی جهات، همانند عناصر
Inline و از برخی جهات دیگر، همانند عناصر Block رفتار کند. این مقدار خاص، inline-block است.
یادآوری میکنم که پراپرتیهای width و height روی عناصر Inline کار
نمیکنند. حالا اگر بخواهیم یک عنصر همانند
عناصر Inline در صفحه نمایش داده شود، یعنی در یک خط جدید نمایش داده نشود (مگر اینکه قبل از آن یک عنصر Block
قرار داشته باشد) اما همانند یک عنصر Block از پراپرتیهای width و height تأثیر بگیرد، کافیست مقدار
inline-block را به پراپرتی display آن عنصر اختصاص دهیم. مثال زیر را ببینید:
بسیار خوب، حالا با هر آنچه که برای درک Box Model نیاز داریم، آشنا هستیم و میتوانیم تصویری از این مفهوم
کلیدی ارائه کنیم. Box Model مفهومی است که بخشهای مختلف یک باکس یعنی content، padding،
border و margin را
تعریف کرده و امکان محاسبهی فضای اشغالشده توسط هر باکس را فراهم میکند.
دیدیم که بخشهای سازندهی یک باکس عبارتند از:
Margin: بیرونیترین بخش باکس عنصر است که به معنای حاشیهی اطراف عنصر یا به عبارت دیگر، فاصلهی بین فریم
(border) عنصر با فریم عناصر مجاور یا عنصر والد است.
Border: فریم یا قاب عنصر است که در حالت پیشفرض، نمایش داده نمیشود اما میتوان آن را با ضخامت، رنگ و
استایل مورد نظر نمایش داد.
Padding: فاصلهی بین محتوای عنصر و فریم آن عنصر است که میتوان مقدار آن را برای چهار سمت عنصر، با
استفاده تعیین کرد.
Content: محتوای عنصر است که درون باکس عنصر قرار میگیرد.
برای درک صحیح مفهوم Box Model باید تفاوت بین عناصر Inline و Block را در نظر داشته باشید:
عرض و ارتفاع عناصر Block را میتوان با استفاده از پراپرتیهای width و height تعیین کرد و پراپرتیهای
مربوط به Margin و Padding و Border باعث میشوند که سایر عناصر از باکس مورد نظر فاصله بگیرند. به عبارت
دیگر، این پراپرتیها روی یک عنصر Block هم اعمال میشوند و هم توسط عناصر یا باکسهای مجاور، به رسمیت شناخته
میشوند.
پراپرتیهای width و height روی عناصر Inline تأثیری ندارند و قابل
اعمال نیستند. همچنین، اعمال پراپرتیهای
مربوط به Margin، Padding و Border روی یک باکس Inline باعث میشود که سایر باکسهای Inline از سمت
چپ و راست
باکس مورد نظر (به صورت افقی) فاصله بگیرند اما از بالا و پایین باکس مورد نظر (به صورت عمودی)، خیر. به
عبارت دیگر، این پراپرتیها روی یک عنصر یا باکس Inline اعمال میشوند اما مقادیر این پراپرتیها توسط عناصر
مجاوری که بالا یا پایین عنصر مورد نظر قرار دارند، نادیده گرفته میشوند.
Box Model دارای دو فرم است: یک فرم استاندارد که به طور پیشفرض در جریان است و یک فرم آلترناتیو یا جایگزین که
میتوان آن را با فرم اصلی جایگزین کرد. اینجا عامل تعیینکننده، یک پراپرتی با نام box-sizing است که میتواند
یکی از دو مقدار content-box یا border-box را دریافت کند. مقدار content-box معادل فرم استاندارد Box Model است
و مقدار border-box معادل فرم آلترناتیو.
فرم استاندارد Box Model
مقدار پیشفرض پراپرتی box-sizing برای همهی عناصر برابر با content-box است و این باعث
میشود که پراپرتیهای
width و height برای بخش Content یا محتوای یک باکس در نظر گرفته شوند.
بنابراین، در این حالت، برای محاسبهی
فضای اشغالشده توسط یک باکس، باید مقادیر Padding و Border را هم به عرض و ارتفاع اضافه کنیم.
به عنوان مثال، فضای اشغال شده توسط عنصر div در مثال زیر برابر است با: 410=350+25+25+5+5 در عرض و
210 =
150+25+25+5+5 پیکسل در ارتفاع.
این همان چیزی است که Standard Box Model نامیده میشود.
فرم آلترناتیو Box Model
با تغییر مقدار پراپرتی box-sizing به border-box، میتوانیم Alternative Box Model را برای
آن عنصر فعال کنیم
که رویکرد منطقیتری را برای محاسبهی فضای اشغاللشده توسط عناصر فراهم میکند. در این مدل، مقداری که برای
width و height تعیین می شود، مقادیر Padding و Border را هم شامل
میشود.
اگر میخواهید همانطور که در بین بسیاری از توسعهدهندگان رایج است، از روش آلترناتیو برای همه عناصر استفاده
کنید، کافیست از یک انتخابگر universal مانند زیر استفاده کنید:
CSS
*, ::before, ::after{box-sizing: border-box;}
با وجودی که این روش کار میکند و باعث میشود که فرم آلترناتیو Box Model برای همهی عناصر صفحه فعال شود، اما
بهتر است از فرم زیر استفاده کنیم:
اشکال روش اول این است که اگر از یک کامپوننت اکسترنال استفاده کنیم که به روش استاندارد متکی باشد، تغییر آن به
فرم آلترناتیو میتواند باعث به هم ریختن آن شود. اما در روش دوم، عناصر کامپوننت اکسترنال همچنان از فرم
استاندارد استفاده میکنند و سایر عناصر از روش آلترناتیو.