وقتی یک Grid Item، خودش هم یک Grid می‌شود: Subgrid

در تمام درس‌های قبل این فصل، هر Grid Item، از دید Grid والدش، فقط یک بلوک بود که در یک یا چند خونه قرار می‌گرفت. اما اگه خود اون Grid Item، محتوای داخلی‌ای داشته باشه که بخوایم دقیقاً با خطوط Grid والدش هم‌تراز باشه، چی؟ اینجاست که Subgrid، یکی از جدیدترین و قدرتمندترین قابلیت‌های CSS Grid، وارد کار می‌شه.

مشکل: Grid تودرتو، بدون هیچ هماهنگی

.parent {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  gap: 16px;
}

.card {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
<div class="parent">
  <div class="card">
    <div>عنوان</div>
    <div>قیمت</div>
  </div>
  <div>آیتم دیگر</div>
  <div>آیتم دیگر</div>
</div>

در این مثال، .card خودش هم یک Grid Container مستقله؛ ولی ستون‌های داخلش (1fr 1fr)، هیچ ارتباطی با ستون‌های Grid والدش (1fr 2fr 1fr) ندارن. اگه بخوایم چند تا از این کارت‌ها، کنار هم، طوری چیده بشن که محتوای داخلی‌شون (مثلاً «عنوان» در همه کارت‌ها)، دقیقاً زیر هم و هم‌تراز باشه، این روش، به‌تنهایی، این هماهنگی رو تضمین نمی‌کنه.

راه‌حل: grid-template-columns: subgrid

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

.card {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
}

وقتی مقدار subgrid رو به‌جای یک مقدار معمولی (مثل 1fr 1fr) برای grid-template-columns یک Grid Item تعریف کنیم، این عنصر، به‌جای ساختن یک سیستم ستون‌بندی کاملاً مستقل و جدید، مستقیماً از همون خطوط ستونی Grid والدش (که در همون محدوده‌ای که با grid-column مشخص کرده، یعنی از خط ۱ تا آخر) استفاده می‌کنه.

یک مثال کامل برای درک بهتر

.card-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.card {
  display: grid;
  grid-column: span 1;
  grid-row: span 3;
  grid-template-rows: subgrid;
  gap: 8px;
}
<div class="card-container">
  <div class="card">
    <h3>عنوان محصول</h3>
    <p>توضیحات کوتاه محصول</p>
    <span>قیمت</span>
  </div>
  <div class="card">
    <h3>عنوان یک محصول با نام خیلی طولانی‌تر</h3>
    <p>توضیحات</p>
    <span>قیمت</span>
  </div>
</div>

در این مثال، هر .card، سه ردیف رو، از Grid والدش (با grid-row: span 3)، در بر می‌گیره؛ و با grid-template-rows: subgrid، ردیف‌های داخلی خودش (یعنی محل قرارگیری تیتر، توضیحات و قیمت)، دقیقاً با همون سه خط ردیفی که Grid والد براش رزرو کرده، هم‌تراز می‌شن. نتیجه این می‌شه که حتی اگه عنوان یک کارت، به‌خاطر طولانی بودن، به دو خط بشکنه و ارتفاعش بیشتر بشه، ردیف مربوط به «قیمت»، در تمام کارت‌های کنار هم، همچنان دقیقاً زیر هم و هم‌تراز باقی می‌مونه.

چرا این قابلیت، قبل از Subgrid، ممکن نبود؟

پیش از معرفی Subgrid، تنها راه‌حل برای این نوع هم‌ترازی، یا استفاده از تکنیک‌های پیچیده و غیرمستقیم بود، یا صرفاً امیدوار بودن به این‌که محتوای داخل هر کارت، به‌طور تصادفی، ارتفاع مشابهی داشته باشه؛ چیزی که در دنیای واقعی، با محتوای متغیر (مثل عناوین محصولات با طول‌های مختلف)، تقریباً هرگز اتفاق نمی‌افته.

Subgrid فقط ساختار را به ارث می‌برد، نه محتوا را

نکته مهمی که باید دقت کرد: وقتی از subgrid استفاده می‌کنیم، اون عنصر، فقط خطوط Grid رو از والدش به ارث می‌بره (یعنی موقعیت و اندازه دقیق خطوط ستونی یا ردیفی)؛ اما آیتم‌های داخلی خودش، همچنان باید به‌طور مستقل، طبق همون قوانین Auto Placement که در درس ۱۳-۸ دیدیم، یا با موقعیت‌دهی دستی (grid-column، grid-row)، در همون خطوط به ارث‌رسیده، چیده بشن.

یک نکته مهم: Subgrid فقط یک محور را هم می‌تواند به ارث ببرد

.card {
  display: grid;
  grid-template-columns: subgrid;
  grid-template-rows: 100px auto 50px; /* این محور مستقل باقی می‌ماند */
}

نیازی نیست هر دو محور (ستون و ردیف) هم‌زمان subgrid باشن؛ می‌شه فقط ستون‌ها رو از والد به ارث برد، در حالی که ردیف‌ها، همچنان به‌طور کاملاً مستقل، توسط خود همون عنصر تعریف می‌شن (یا برعکس).

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

Subgrid، یکی از جدیدترین قابلیت‌های CSS Grid‌ه و پشتیبانیش، نسبت به مباحث پایه‌ای‌تر Grid که در این فصل دیدیم، محدودتره. پیش از استفاده گسترده از این ویژگی در پروژه‌های واقعی، بررسی وضعیت پشتیبانی مرورگرهای هدف پروژه، ضروریه.

یک جدول جمع‌بندی: Grid تودرتوی معمولی در برابر Subgrid

ویژگی Grid تودرتوی معمولی Subgrid
ارتباط با خطوط Grid والد کاملاً مستقل، بدون هیچ هماهنگی مستقیماً از خطوط والد استفاده می‌کند
هم‌ترازی محتوا بین چند آیتم مشابه نیازمند تکنیک‌های جایگزین یا شانس خودکار و دقیق
پشتیبانی مرورگر گسترده و دیرینه جدیدتر؛ نیاز به بررسی

نکات مهم

  • Subgrid، به یک Grid Item اجازه می‌دهد به‌جای ساختن ستون‌بندی یا ردیف‌بندی مستقل، مستقیماً از خطوط Grid والدش استفاده کند.
  • Subgrid فقط ساختار خطوط را به ارث می‌برد، نه محتوا را؛ آیتم‌های داخلی همچنان باید به‌طور مستقل چیده شوند.
  • می‌توان فقط یکی از دو محور (ستون یا ردیف) را subgrid کرد، در حالی که محور دیگر مستقل باقی می‌ماند.

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

  • تصور اینکه subgrid، محتوای داخلی را هم به‌طور خودکار می‌چیند؛ در حالی که فقط خطوط ساختاری را به ارث می‌برد.
  • استفاده از subgrid بدون تعریف صحیح grid-column یا grid-row روی همان عنصر، که مشخص می‌کند کدام بخش از خطوط والد باید به ارث برسد.
  • استفاده گسترده از subgrid در پروژه‌هایی با نیاز به پشتیبانی مرورگرهای قدیمی‌تر، بدون بررسی وضعیت پشتیبانی.

جمع‌بندی

Subgrid، به یک Grid Item اجازه می‌دهد، به‌جای ساختن یک سیستم ستون‌بندی یا ردیف‌بندی کاملاً مستقل، مستقیماً از خطوط Grid والدش استفاده کند؛ این قابلیت، مشکل هم‌ترازی دقیق محتوا بین چند عنصر مشابه (مثل کارت‌های محصول با محتوای متغیر) را، بدون نیاز به تکنیک‌های پیچیده جایگزین، به‌طور خودکار حل می‌کند.