ابزارهای اندازه‌گیری هوشمند: fr، minmax()، repeat()، auto-fit و auto-fill

در درس‌های قبل، با fr (که در فصل ۶ هم دیدیم) و تابع repeat() آشنا شدیم. حالا وقتشه این ابزارها رو با دو تابع بسیار قدرتمند دیگه ترکیب کنیم: minmax() که محدوده اندازه هر Track رو کنترل می‌کنه، و auto-fit/auto-fill که به Grid اجازه می‌دن، بدون هیچ Media Query‌ای، خودش تعداد ستون‌های مناسب رو، بر اساس فضای موجود، محاسبه کنه.

مرور سریع: fr

.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
}

همون‌طور که در فصل ۶ کامل دیدیم، fr نشون می‌ده هر ستون، چه نسبتی از فضای باقی‌مانده رو باید بگیره؛ در این مثال، ستون وسط، دقیقاً دو برابر ستون‌های کناری فضا می‌گیره.

minmax(): تعیین یک محدوده، به‌جای یک مقدار ثابت

.container {
  display: grid;
  grid-template-columns: minmax(150px, 300px) 1fr;
}

تابع minmax() اجازه می‌ده، به‌جای یک مقدار ثابت، یک بازه (حداقل و حداکثر) برای اندازه یک Track تعریف کنیم. در این مثال، ستون اول، هرگز از ۱۵۰ پیکسل کوچک‌تر و هرگز از ۳۰۰ پیکسل بزرگ‌تر نمی‌شه؛ ولی بین این دو مقدار، بر اساس فضای موجود، به‌طور انعطاف‌پذیر تغییر می‌کنه.

ترکیب minmax() با fr

.container {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) minmax(200px, 1fr);
}

یکی از ترکیب‌های بسیار رایج، استفاده از minmax() با یک حداقل ثابت و یک حداکثر 1frه؛ یعنی «این ستون، حداقل ۲۰۰ پیکسل باشه، ولی اگه فضا اجازه داد، به‌طور مساوی با بقیه ستون‌ها رشد کنه». این الگو، برای جلوگیری از خیلی باریک شدن ستون‌ها در صفحه‌نمایش‌های کوچک، بسیار مفیده.

مرور سریع: repeat()

.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

همون‌طور که در درس ۱۳-۳ دیدیم، repeat() از تکرار دستی مقادیر یکسان جلوگیری می‌کنه. حالا می‌بینیم چطور می‌شه این تابع رو با minmax() و کلیدواژه‌های هوشمند ترکیب کرد.

مشکل: تعداد ستون‌های ثابت، برای همه صفحه‌نمایش‌ها مناسب نیست

.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

این Rule، همیشه دقیقاً چهار ستون می‌سازه؛ صرف‌نظر از عرض صفحه‌نمایش. در یک موبایل کوچک، این چهار ستون، ممکنه اونقدر باریک بشن که محتوا اصلاً خوانا نباشه. راه‌حل سنتی، نوشتن چند Media Query جداگانه برای تغییر تعداد ستون‌ها در اندازه‌های مختلفه؛ ولی Grid، یک راه‌حل هوشمندتر و بدون نیاز به Media Query هم داره.

auto-fit و auto-fill: تعداد ستون خودکار

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

این یکی از قدرتمندترین و پرکاربردترین الگوهای CSS Grid مدرن‌ه. به‌جای دادن یک عدد ثابت به repeat()، از کلیدواژه auto-fit استفاده کردیم. این ترکیب می‌گه: «هر چند ستونی که با حداقل عرض ۲۰۰ پیکسل، در فضای موجود جا می‌شه، خودت بساز؛ و اگه فضای اضافه‌ای موند، بین همون ستون‌های موجود (به‌خاطر 1fr) تقسیمش کن».

نتیجه این می‌شه که، بدون نوشتن حتی یک خط Media Query، تعداد ستون‌های گالری، به‌طور کاملاً خودکار و پیوسته، با عرض صفحه‌نمایش هماهنگ می‌شه: در موبایل، شاید فقط یک یا دو ستون جا بشه؛ در تبلت، سه یا چهار ستون؛ و در یک مانیتور بزرگ، شاید شش یا هفت ستون.

تفاوت auto-fit و auto-fill

این دو کلیدواژه، در نگاه اول، رفتار مشابهی دارن، ولی یک تفاوت ظریف و مهم دارن که فقط وقتی خودش رو نشون می‌ده که فضای Container، بیشتر از فضای مورد نیاز آیتم‌های موجود باشه.

.fit-example {
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.fill-example {
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
کلیدواژه رفتار وقتی آیتم‌های واقعی کم باشند
auto-fill ستون‌های خالی (بدون محتوا) را هم می‌سازد تا فضا پر شود؛ آیتم‌های موجود، عرض اصلی خودشان (مثلاً 150px) را حفظ می‌کنند
auto-fit ستون‌های خالی را از بین می‌برد (Collapse می‌کند) و اجازه می‌دهد آیتم‌های موجود، فضای اضافه را با هم پر کنند (به‌خاطر 1fr)

یک مثال بصری برای درک بهتر این تفاوت

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  width: 600px;
}
<div class="container">
  <div>آیتم ۱</div>
  <div>آیتم ۲</div>
</div>

در این مثال، با عرض Container برابر ۶۰۰ پیکسل و حداقل عرض هر آیتم ۱۵۰ پیکسل، جا برای چهار ستون وجود داره؛ ولی فقط دو آیتم واقعی داریم. با auto-fit، این دو آیتم، فضای خالی رو با هم تقسیم می‌کنن و هرکدوم به ۳۰۰ پیکسل می‌رسن (چون 1fr اجازه رشد می‌ده). با auto-fill، برعکس، دو ستون خالی (بدون محتوا) هم ساخته می‌شن، و دو آیتم واقعی، همچنان روی همون ۱۵۰ پیکسل اصلی باقی می‌مونن.

کدام حالت، معمولاً انتخاب بهتری است؟

در اکثر کاربردهای عملی (مثل گالری‌های تصویر یا کارت‌های محصول)، auto-fit معمولاً انتخاب رایج‌تریه؛ چون معمولاً می‌خوایم آیتم‌های موجود، فضای خالی رو پر کنن، نه اینکه فضای خالی، به شکل ستون‌های نامرئی باقی بمونه.

یک مثال کامل و کاربردی: گالری کاملاً واکنش‌گرا

.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
}
<div class="product-grid">
  <div>محصول ۱</div>
  <div>محصول ۲</div>
  <div>محصول ۳</div>
  <div>محصول ۴</div>
  <div>محصول ۵</div>
</div>

این چند خط، یک گالری محصول کاملاً واکنش‌گرا می‌سازه؛ بدون نیاز به حتی یک Media Query. هر کارت، حداقل ۲۲۰ پیکسل عرض داره، و تعداد ستون‌ها، به‌طور خودکار، با عرض صفحه هماهنگ می‌شه.

نکات مهم

  • minmax() یک بازه (حداقل و حداکثر) برای اندازه یک Track تعریف می‌کند، به‌جای یک مقدار ثابت.
  • ترکیب repeat(auto-fit, minmax(...)) امکان ساخت Gridهای کاملاً واکنش‌گرا را، بدون نیاز به Media Query، فراهم می‌کند.
  • تفاوت auto-fit و auto-fill فقط زمانی مشهود است که آیتم‌های واقعی، کمتر از تعداد ستون‌های قابل‌ساخت باشند؛ auto-fit ستون‌های خالی را جمع می‌کند، auto-fill آن‌ها را نگه می‌دارد.

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

  • استفاده از repeat() با یک عدد ثابت در چیدمان‌های واکنش‌گرا، به‌جای استفاده از auto-fit که نیاز به Media Query را کاهش می‌دهد.
  • قاطی کردن auto-fit و auto-fill، بدون توجه به رفتار متفاوتشان در وجود ستون‌های خالی.
  • فراموش کردن مقدار حداقل مناسب در minmax()، که می‌تواند باعث بسیار باریک شدن ستون‌ها در صفحه‌نمایش‌های کوچک شود.

جمع‌بندی

تابع minmax() یک بازه اندازه برای هر Track تعریف می‌کند، و ترکیب آن با repeat(auto-fit, ...)، یکی از قدرتمندترین الگوهای CSS Grid مدرن است که امکان ساخت چیدمان‌های کاملاً واکنش‌گرا، بدون نیاز به هیچ Media Query‌ای، فراهم می‌کند. تفاوت auto-fit و auto-fill، در نحوه برخورد با ستون‌های خالی احتمالی است؛ auto-fit معمولاً برای اکثر کاربردهای عملی، انتخاب مناسب‌تری محسوب می‌شود.