فاصله‌گذاری مدرن بین آیتم‌ها: gap، row-gap و column-gap

در درس‌های قبل، چندبار به‌طور گذرا از gap استفاده کردیم، بدون این‌که کامل توضیحش بدیم. حالا وقتشه این Property مهم و مدرن رو، که فاصله‌گذاری بین Flex Itemها رو به روشی تمیزتر از Margin سنتی ممکن می‌کنه، کامل ببینیم.

مشکل سنتی: فاصله‌گذاری با Margin

.item {
  margin-inline-end: 16px;
}

.item:last-child {
  margin-inline-end: 0;
}

پیش از معرفی gap در Flexbox، برای ایجاد فاصله بین آیتم‌ها، معمولاً باید به هر آیتم یک margin (مثلاً در سمت پایان) اضافه می‌کردیم؛ و بعد، برای جلوگیری از فاصله اضافه و ناخواسته بعد از آخرین آیتم، مجبور بودیم اون margin رو مخصوصاً برای آخرین آیتم (با یک Selector مثل :last-child که در فصل ۳ دیدیم) صفر کنیم. این روش، هم پرحجم‌تر بود، هم مستعد فراموشی و خطا.

gap: راه‌حل مدرن و ساده

.container {
  display: flex;
  gap: 16px;
}
<div class="container">
  <div>آیتم ۱</div>
  <div>آیتم ۲</div>
  <div>آیتم ۳</div>
</div>

Property به اسم gap، وقتی روی خود Flex Container تعریف بشه، به‌طور خودکار، یک فاصله مشخص، فقط بین آیتم‌های پشت‌سرهم ایجاد می‌کنه؛ بدون این‌که قبل از اولین آیتم یا بعد از آخرین آیتم، هیچ فاصله اضافه‌ای اضافه بشه. این دقیقاً همون مشکلی‌ست که در روش سنتی Margin، نیاز به یک Selector اضافه برای حلش داشتیم.

row-gap و column-gap: کنترل مستقل هر جهت

.container {
  display: flex;
  flex-wrap: wrap;
  row-gap: 20px;
  column-gap: 10px;
}

Property به اسم gap، در واقع یک شورت‌هند برای دو Property جداگانه‌ست: row-gap (فاصله بین ردیف‌ها) و column-gap (فاصله بین ستون‌ها). این تفکیک، مخصوصاً زمانی معنا پیدا می‌کنه که flex-wrap: wrap فعال باشه و آیتم‌ها به چند خط بشکنن؛ چون در اون حالت، هم فاصله بین آیتم‌های یک خط (که با column-gap کنترل می‌شه، در حالت row) و هم فاصله بین خود خطوط (که با row-gap کنترل می‌شه)، قابل تنظیم مستقل هستن.

نکته مهم: معنای row-gap و column-gap به flex-direction وابسته است

باید دقت کرد که این دو Property، دقیقاً مثل خیلی از مفاهیم دیگه‌ای که در این فصل دیدیم، به محورهای Main و Cross وابسته‌ان، نه صرفاً «افقی» و «عمودی» ثابت:

  • وقتی flex-direction: row باشه: column-gap فاصله بین آیتم‌ها در طول Main Axis (افقی) رو کنترل می‌کنه، و row-gap فاصله بین خطوط شکسته‌شده در طول Cross Axis (عمودی) رو.
  • وقتی flex-direction: column باشه: این رابطه برعکس می‌شه؛ row-gap فاصله بین آیتم‌ها در طول Main Axis (که حالا عمودیه) رو کنترل می‌کنه.

شورت‌هند gap با دو مقدار

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px 10px;
}

وقتی gap با دو مقدار نوشته بشه، مقدار اول همیشه row-gap رو تعریف می‌کنه و مقدار دوم، column-gap رو؛ دقیقاً معادل نوشتن جداگانه row-gap: 20px; column-gap: 10px;.

.container {
  gap: 16px; /* هر دو row-gap و column-gap برابر 16px */
}

اگه فقط یک مقدار بدیم، این مقدار، به‌طور خودکار، هم برای row-gap و هم برای column-gap اعمال می‌شه.

یک مثال عملی: گالری تصاویر با فاصله یکسان در هر دو جهت

.gallery {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.gallery-item {
  width: 150px;
  height: 150px;
}

در این مثال (که مشابه چیزی‌ست که در درس ۱۲-۳ هم دیدیم)، Property به اسم gap، فاصله یکسان و منظمی، هم بین آیتم‌های هر ردیف (Main Axis)، و هم بین خود ردیف‌ها (Cross Axis)، ایجاد می‌کنه؛ بدون نیاز به هیچ محاسبه دستی Margin یا نگرانی درباره فاصله اضافه در لبه‌های Container.

مزیت مهم gap نسبت به Margin: عدم تأثیر بر لبه‌های بیرونی Container

.container {
  display: flex;
  gap: 20px;
  border: 1px solid #ccc;
  padding: 16px;
}

یکی از مزیت‌های کلیدی gap، اینه که، برخلاف Margin که ممکنه (بسته به تنظیمات) با Padding والد یا لبه Container تداخل ایجاد کنه، gap فقط و فقط بین خود آیتم‌ها فضا ایجاد می‌کنه؛ فاصله بین اولین/آخرین آیتم و لبه Container، کاملاً و تنها توسط padding خود Container کنترل می‌شه؛ بدون هیچ تداخل یا محاسبه پیچیده‌ای.

پشتیبانی مرورگرها

gap در Flexbox، امروزه در تمام مرورگرهای مدرن پشتیبانی گسترده‌ای داره. لازم به ذکره که این Property، در ابتدا مخصوص Grid طراحی شده بود (که در فصل بعدی کامل بررسیش می‌کنیم) و بعداً به Flexbox هم اضافه شد؛ برای همین، در پروژه‌هایی که نیاز به پشتیبانی از مرورگرهای بسیار قدیمی‌تر دارن، بررسی وضعیت پشتیبانی همچنان توصیه می‌شه.

یک مقایسه سریع: Margin سنتی در برابر gap

ویژگی Margin سنتی gap
نیاز به Selector اضافه برای آخرین آیتم بله (مثل :last-child) خیر
فاصله اضافه در لبه‌های Container احتمال دارد (بسته به تنظیم) هرگز
کنترل مستقل ردیف و ستون نیازمند تنظیم دستی پیچیده‌تر ساده، با row-gap و column-gap

نکات مهم

  • gap فاصله را فقط بین آیتم‌های پشت‌سرهم ایجاد می‌کند؛ نه قبل از اولین یا بعد از آخرین آیتم.
  • row-gap و column-gap، بسته به مقدار flex-direction، به Main Axis یا Cross Axis وابسته‌اند، نه صرفاً افقی و عمودی ثابت.
  • در شورت‌هند gap با دو مقدار، ترتیب همیشه ابتدا row-gap و سپس column-gap است.

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

  • ادامه استفاده از Margin دستی به‌همراه Selectorهای پیچیده برای فاصله‌گذاری، در حالی که gap این کار را بسیار ساده‌تر انجام می‌دهد.
  • قاطی کردن ترتیب مقادیر در شورت‌هند دو‌مقداری gap (اشتباهاً column-gap را اول در نظر گرفتن).
  • فراموش کردن این‌که معنای row-gap و column-gap، با تغییر flex-direction از row به column، جابه‌جا می‌شود.

جمع‌بندی

Property به اسم gap، فاصله‌گذاری بین Flex Itemها را، بدون نیاز به Margin دستی و Selectorهای اضافه، به‌طور تمیز و مدرن فراهم می‌کند. این Property، شورت‌هند دو Property مستقل row-gap و column-gap است که به‌ترتیب فاصله بین ردیف‌ها و ستون‌ها را کنترل می‌کنند؛ معنای دقیق این دو، بسته به مقدار flex-direction Container، بین Main Axis و Cross Axis جابه‌جا می‌شود.