درک و نحوه کار با CSS Margins

دوشنبه 28 بهمن 1398

یکی از مسائلی که افراد زیادی با آن درگیر هستند حاشیه‌ها (Margin) می‌باشند، که به نظر می‌رسد بسیار ساده‌اند، با این حال این پتانسیل را دارند که برخی از مسائل واقعا عجیب را ایجاد کنند.

درک و نحوه کار با CSS Margins

marginها یک بخش کوچک از CSS هستند. به نظر می‌رسد که خیلی ساده این پراپرتی را مساوی یک مقدار قرار می‌دهیم و کار می‌کند، اما همین‌طور که پیش می‌روید متوجه می‌شوید که اتفاقات زیادی در جریان است.

شما به سادگی یک margin را اضافه می‌کنید و فضای خالی اطراف آن عنصر ایجاد می‌شود. اما می‌بینید که آن‌ها در یک موقعیت نسبت به موقعیت دیگری متفاوت عمل می‌کنند، یا margin-top را به عنصر فرزند اضافه می‌کنید و در عوض عنصر والد کمی پایین می‌رود.

اینجاست که ناامید می‌شوید.

امیدوارم در این مقاله نحوه عملکرد marginها کمی برای شما روشن شود. ما به برخی مشکلات رایج که رخ می‌دهد، و همچنین راه‌حل‌های ساده برای این مسائل می‌پردازیم.

Margin چیست؟

قبل از اینکه به این موضوع بپردازیم، می‌خواهیم مطمئن شویم که همه می‌دانند که margin چیست؟

marginها حاشیه خارجی یک بخش هستند، یعنی فاصله بین یک عنصر با عناصر دیگر. سپس خود محتوا، padding و border می‌آیند. به عبارت دیگر، این فضا کاملا خالی است که می‌توانیم از آن برای ایجاد فضا بین یک عنصر و عنصر دیگر در طرح خود استفاده کنیم.

سر و کار داشتن با stylesheetsهای user-agent

مرورگرها به طور پیش‌فرض با مقدار شگفت‌انگیزی از CSS همراه هستند، که ما آن‌ها را stylesheetsهای user-agent (عامل کاربر) می‌نامیم. این استایل‌ها به این صورت هستند که بدون هیچ CSSای از طرف ما انجام می‌شوند، < h1> بزرگ‌تر از < h2> است، و < body> دارای حاشیه‌ای است که همیشه ما تمایل داریم آن را حذف کنیم.

این استایل‌ها مهم هستند،‌ اما آن‌ها به یکی از بزرگ‌ترین مسائل منجر می‌شوند که مردم margin را نسبت به آن‌ها اعمال می‌کنند. Marginها به صورت پیش‌فرض نسبت به همه عناصر 0 نیستند،‌ و این موضوع می‌تواند منجر به ایجاد مسائل عجیب و غریبی شود که به زودی به بررسی آن‌ها خواهیم پرداخت.

Listها،‌ blockquoteها،‌ paragraphها و headingها همه دارای margin هستند (در میان سایر عناصر). در حالی که گاهی اوقات آن‌ها فقط کمی اذیت‌کننده هستند، margin پیش‌فرض بر روی پاراگراف‌ها و headingها به نظر می‌رسد موردی است که بیشترین مشکلات را به وجود می‌آورند.

به طور پیش‌فرض margin چپ و راست یک عنصر text با 0 تنظیم شده است، اما همه آن‌ها با margin-top و margin-bottom قرار می‌گیرند.

این بدان معناست که اگر ما به طور صریح margin را هم تنظیم نکرده باشیم،‌ بین عناصر موجود در صفحه فضا وجود دارد.

فرو رفتن marginها در یکدیگر

فرو رفتن marginها جایی است که اغلب سردرگمی‌ها شروع می‌شود.

وقتی دو عنصر marginهای عمودی دارند که با هم در تماس هستند،‌ آن‌ها با یکدیگر ادغام می‌شوند.

این یک رفتار عجیب است،‌ و این فقط برای marginهای عمودی است (بالا و پایین)،‌ به همین دلیل مردم هنگام استفاده از آن‌ها گیج و سردرگم می‌شوند.

با مثال زیر می‌توانیم این رفتار را در عمل ببینیم:

p {
  font-size: 18px;
  margin-bottom: 40px;
}

.links {
  margin-top: 40px;
}

برای نشان دادن آنچه در اینجا اتفاق می‌افتد، کلاس links. در آخرین پاراگراف است (<p class="links" >) ، که شامل دو لینک در آن است.

وقتی کسی کاری شبیه این انجام می‌دهد، انتظار دارد حاشیه بین پاراگراف میانی و لینک‌های زیر آن 80px شود (40px + 40px)، اما در واقعیت این 40px است. دو margin با یکدیگر در تماس هستند، پس آن‌ها با یکدیگر ادغام می‌شوند.

                                            

برای اینکه بهتر این را نشان دهیم، بیاید margin-bottom ی <p> را 100px بگذاریم:

p {
  font-size: 18px;
  margin-bottom: 100px;
}

.links {
  margin-top: 40px;
}

دوباره دو margin به یکدیگر اضافه نمی‌شوند،‌ آن‌ها در یکدیگر فرو می‌روند، پس فضای کل در اینجا 100px است.

                                           

این چیز خوبی است

در مواردی مثل این،‌ این موضوع در واقع چیز خوبی است. اگر چندین عنصر با marginهای مختلف وجود داشته باشد،‌ دیگر نیازی به اضافه کردن marginها در کنار هم نیست تا ببینیم فاصله بین عناصر چقدر بزرگ است زیرا می‌توانیم به این واقعیت اعتماد کنیم که margin بزرگ‌تر همیشه برنده است.

چه وقت چیز خوبی نیست

یکی از مواردی که فرو رفتن margin باعث سردرگمی می‌شود وقتی است که اولین فرزند درون عنصر دارای margin-top است که با margin-top والد ادغام می‌شود.

بیایید دوباره به همان عکس نگاهی بیاندازیم:

                                       

بین بالای viewport و مستطیل سیاه یک فضای سفید وجود دارد. این برای body نیست (این فضا خیلی بزرگ‌تر از  8px margin ی body است که وجود دارد).

پس این از کجا آمده است؟

در واقع این از < h1> در بالای مستطیل سیاه آمده است.

به خاطر دارید که گفتم stylehsheetهای user-agent می‌توانند کارهای عجیبی انجام دهند؟

برای توضیح دقیق آنچه در اینجا رخ داده است، بیایید یک margin-top خیلی بزرگ‌تر برای h1 اضافه کنیم.

.card {
  background: #000;
  color: white;
  width: 560px;
  margin: 0 auto;
}

h1 {
  font-size: 24px;
  margin-top: 100px;
}

p {
  font-size: 18px;
  margin-bottom: 100px;
}

.links {
  margin-top: 10px;
}

می‌بینیم مردم این کار را همیشه انجام می‌دهند، سعی می‌کنند عنوان را در والد خود قرار دهند. با این حال، به جای اینکه طبق انتظار آنان کار کند، یک فضای بسیار زیاد در بالای آن دریافت می‌کنند!

                                        

دلیل این امر این است که margin-top در بالای < h1> با margin-top در عنصر والد ادغام می‌شود.

در این حالت هیچ جدایی از قسمت بالای فرزند و والد وجود ندارد. بنابراین وقتی margin-top را به فرزند اضافه می‌کنیم، با margin-top والد در تماس است، و همانطور که در بالا دیدیم،‌ وقتی دو margin با یکدیگر در تماس باشند،‌ آن‌ها در یک margin واحد ادغام می‌شوند.

بنابراین در حالی که ما به فرزند margin می‌دهیم، برای والد اعمال می‌شود.

به همین دلیل مردم از CSS متنفر هستند.

از این رو، در کد بالا ما به همه پاراگراف‌ها یک margin-bottom داده‌ایم. این margin در عناصر p.link با margin-bottom عنصر card. در تماس است، که این بدان معناست که این دو با هم ادغام می‌شوند و margin روی عنصر card. به جای links تاثیر می‌گذارد.

اگرچه این مسأله مشکلی برای سایتی که ما در حال ساخت آن هستیم ایجاد نمی‌کند، اما اگر بعدا تصمیم گرفتیم عناصر دیگری را به صفحه اضافه کنیم می‌تواند مشکلاتی ایجاد کند.

مشکل این است که ما از margin برای هدف اشتباه استفاده می‌کنیم.

اگر ما بخواهیم فضایی را بین بالای عنصر card. و فرزندان درون آن ایجاد کنیم، به هر حال نباید از margin استفاده کنیم.

قانون کلی ما این است که اگر فضای خالی می‌خواهید از margin استفاده کنید. اگر پس‌زمینه (background) بیشتری می‌خواهید، از padding استفاده کنید.

در این حالت ما می‌خواهیم card. بک‌گراند بیشتری داشته باشد، بنابراین نباید به فرزندان آن margin اضافه کنیم. در عوض ما باید padding را به خود عنصر اضافه کنیم.

              

در تصویر بالا، ما می‌توانیم padding و margin را مشاهده کنیم. < h1> در بالا همچنان دارای margin است، اما دیگر با card. ادغام نمی‌شود، زیرا padding اضافه شده است. این امر مانع از آن می‌شود تا marginی card. و h1 با یکدیگر در تماس باشند.

از آنجا که padding فضای کافی بین < p>ها و < h1>ها اضافه کرده است،‌ اکنون می‌توانیم marginهایی که قبلا به آن‌ها اضافه کرده‌ایم را حذف کنیم.

                           

یک روش آسان برای جلوگیری از فرو رفتن marginها وجود دارد

اول از همه، قانون کلی که در بالا در مورد آن صحبت کردیم وجود دارد:

اگر به فضای خالی نیاز دارید، از margin استفاده کنید.

اگر به پس زمینه بیشتری نیاز دارید، از padding استفاده کنید.

این کار بیشتر اوقات آزاردهنده است. اما بیایید یک قانون دیگر اضافه کنیم که بیشتر کمک‌کننده است:

سعی کنید از استفاده از margin-top خودداری کنید، مگر اینکه واقعا به آن احتیاج داشته باشید.

این قانون کمی با استایل‌های user-agent تضاد دارد، که یک margin-top و margin-bottom را برای دسته‌ای از عناصر تنظیم می‌کند، که یکی از دلایلی است که ما اغلب چنین کاری را انجام می‌دهیم:

h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
ol {
 margin: 0 0 1em 0;   
}

این امر بسیاری از مشکلاتی که ناشی از فرو رفتن marginها در یکدیگر است را از بین می‌برد.

این بهترین راه‌حل نیست، و ما اغلب از margin-top کمی در subtitleها در موقعیت‌های خاص استفاده می‌کنیم، اما می‌تواند کمک‌کننده باشد.

ایمان مدائنی

نویسنده 1299 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید