تاروپود — خودآموز HTML و CSS

فصل ۵ از ۱۱

پیشرفت ترم
۰٪

ترم ۳ · Layout: چیدمان

grid: دو محور

فصل ۵پیش‌نمایش رایگان
۱۱ دقیقه مطالعه فصل ۵

در این فصل چه می‌سازی#

آخر این فصل یک گالری از کارت‌ها داری که در سطر و ستونی منظم چیده شده‌اند: چند ستونِ برابر، با فاصله‌های یکسان، که تر و تمیز زیر هم و کنار هم می‌نشینند. تا اینجا با flexbox چیزها را روی یک خط می‌چیدی — یک ردیف یا یک ستون. اینجا برای اولین‌بار سطر و ستون را با هم می‌سازی و یک ابزار تازه یاد می‌گیری که دقیقاً برای همین کار ساخته شده: grid.

طرح یک grid با سه ستون برابر و دو سطر؛ فضای خالی صفحه به‌صورت سهم‌های مساوی بین ستون‌ها تقسیم شده، با خط‌های راهنما بین خانه‌ها

آخر این فصل می‌توانی:

  • یک عنصر را با display: grid به یک grid تبدیل کنی
  • با grid-template-columns تعداد و پهنای ستون‌ها را تعیین کنی
  • با واحد fr فضای خالی را عادلانه بین ستون‌ها پخش کنی
  • بگویی کِی grid بهتر از flexbox است و چرا

قبل از شروع#

  • از فصل ۲ (همین ترم): display: flex و اینکه «چیدن روی یک محور» یعنی چه — grid درست از همین‌جا فراتر می‌رود.
  • از فصل ۴ (همین ترم): gap — همان property را اینجا هم به‌کار می‌بریم.
  • از ترم ۲: background-color، border-radius و padding — تا کارت‌ها روی صفحه پیدا و خوش‌فرم باشند.

مثل همیشه فقط یک مرورگر لازم داری، یا فقط همین آزمایشگاه.

۱. دو محور، نه یک محور#

flexbox را یادت هست: چیزها را در یک جهت می‌چیند — یا یک ردیف افقی، یا یک ستون عمودی. یک محور اصلی داری و همه‌چیز روی آن ردیف می‌شود. برای یک منو، یک نوار دکمه، یا وسط‌چین‌کردن، عالی است.

ولی خیلی از چیزهایی که روی وب می‌بینی یک محور نیستند، دو محورند: یک گالری عکس، یک صفحهٔ محصولات، جدولِ داشبورد. این‌ها باید هم در جهت افقی مرتب باشند و هم در جهت عمودی — یعنی ستون‌ها زیرِ هم خط بیفتند و سطرها هم‌تراز بمانند. با flexbox و flex-wrap می‌شد چیزها را به خط بعد شکست، ولی آن‌جا مرورگر خودش تصمیم می‌گرفت چه چیزی کجا برود و ستون‌ها لزوماً تراز نمی‌ماندند.

grid برای همین ساخته شده: یک چیدمانِ سطر و ستون که تو خودت خط‌کشی‌اش می‌کنی، و بعد محتوا سرِ جای خانه‌هایش می‌نشیند. بیا با یک گالریِ ساده شروع کنیم. در آزمایشگاه این HTML را بنویس:

<section class="gallery">
  <article class="card">کارت ۱</article>
  <article class="card">کارت ۲</article>
  <article class="card">کارت ۳</article>
  <article class="card">کارت ۴</article>
  <article class="card">کارت ۵</article>
  <article class="card">کارت ۶</article>
</section>

و یک استایلِ ساده بده تا کارت‌ها دیده شوند:

body {
  background-color: #f6edda;
  padding: 24px;
}

.card {
  background-color: #2a6b93;
  color: #ffffff;
  padding: 24px;
  border-radius: 8px;
  text-align: center;
}

چک کن: شش مستطیلِ آبیِ توپُر می‌بینی که پشتِ‌سرِ هم، هر کدام در یک خطِ جدا، از بالا تا پایین چیده شده‌اند. هر کارت کلِ عرض را گرفته. الان این‌ها یک ستونِ ساده‌اند؛ می‌خواهیم‌شان به سه ستون تبدیل کنیم.

۲. display: grid و ساختن ستون‌ها#

اولین قدم این است که به عنصرِ دربرگیرنده — یعنی .gallery که همهٔ کارت‌ها داخلش هستند — بگویی «تو یک grid هستی». دقیقاً مثل display: flex، این‌بار می‌نویسی display: grid:

.gallery {
  display: grid;
}

حالا صفحه را نگاه کن. انتظار داری کارت‌ها کنارِ هم بروند و ستون بسازند... ولی هیچ اتفاقی نمی‌افتد! کارت‌ها هنوز پشتِ‌سرِ هم، هر کدام در یک خط، چیده‌اند. انگار display: grid کاری نکرد.

🔧 اگر کار نکرد: بله، همین درست است و باید همین را ببینی. display: grid فقط grid را روشن می‌کند؛ ولی تو هنوز به آن نگفته‌ای چند ستون داشته باشد. مرورگر پیش‌فرض یک ستون می‌سازد، پس همه‌چیز مثل قبل زیرِ هم می‌ماند. تعداد و پهنای ستون‌ها با یک property جدا تعیین می‌شود: grid-template-columns. تا این را ننویسی، grid چیزی برای چیدن ندارد.

پس یک خط دیگر اضافه کن و سه ستون بخواه. یک راه این است که پهنای هر ستون را با px بدهی:

.gallery {
  display: grid;
  grid-template-columns: 200px 200px 200px;
}

چک کن: حالا کارت‌ها سه‌تا سه‌تا کنارِ هم رفتند و دو سطر ساختند: سه کارت بالا، سه کارت پایین. این همان grid است — سطر و ستون، با هم. عددِ 200px را برای هر ستون نوشتیم، پس هر ستون دقیقاً ۲۰۰ پیکسل پهناست.

اما یک مشکل هست: اگر صفحه پهن‌تر از سه‌تا ۲۰۰ پیکسل باشد، سمتِ چپِ grid فضای خالیِ استفاده‌نشده می‌ماند؛ و اگر صفحه باریک‌تر شود، ستون‌ها جا نمی‌شوند و از لبه بیرون می‌زنند. عددِ ثابتِ px با عرضِ صفحه بالا و پایین نمی‌رود. برای همین یک واحدِ مخصوصِ grid داریم که این را حل می‌کند.

۳. واحد fr: سهم از فضای خالی#

fr کوتاه‌شدهٔ «fraction» است، یعنی سهم. به‌جای اینکه بگویی «این ستون ۲۰۰ پیکسل»، می‌گویی «این ستون یک سهم از فضای موجود». مرورگر کلِ فضای خالی را برمی‌دارد و بین سهم‌ها پخش می‌کند. سه ستونِ 1fr یعنی «فضا را سه قسمتِ مساوی کن، به هر ستون یکی». عددِ px را با fr عوض کن:

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

چک کن: حالا سه ستون کلِ عرض را پُر می‌کنند و برابرند، بدون هیچ فضای خالیِ اضافه در کنار. عرضِ آزمایشگاه را کم و زیاد کن (یا پنجره را باریک کن) و ببین ستون‌ها با هم کش می‌آیند و جمع می‌شوند، ولی همیشه سه‌تا و هم‌عرض می‌مانند. این کاری است که px نمی‌توانست بکند.

حالا با نسبت‌ها بازی کن. اولین ستون را دو سهم بده و بقیه را یک سهم:

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

چک کن: ستونِ اول حالا دقیقاً دو برابرِ هر کدام از دو ستونِ دیگر پهن است — چون دو سهم از چهار سهمِ کل را گرفته. همین است زیباییِ fr: با نسبت فکر می‌کنی، نه با عددِ ثابت. برای ادامه، برش گردان به 1fr 1fr 1fr تا سه ستونِ برابر داشته باشیم.

💡 نکته: می‌توانی fr و px را قاطی کنی. مثلاً grid-template-columns: 200px 1fr یعنی «ستونِ اول دقیقاً ۲۰۰ پیکسل، ستونِ دوم هرچه فضا ماند». این برای وقتی خوب است که یک ستون باید اندازهٔ ثابت داشته باشد (مثل یک نوارِ کناری) و بقیه انعطاف‌پذیر بمانند.

۴. gap: فاصله بین خانه‌ها#

الان کارت‌ها به هم چسبیده‌اند. gap را از flexbox می‌شناسی — همان‌جا فاصلهٔ بین آیتم‌ها را می‌ساخت. در grid دقیقاً همان‌طور کار می‌کند، با یک امتیازِ اضافه: هم فاصلهٔ بینِ ستون‌ها را می‌سازد و هم فاصلهٔ بینِ سطرها را، با یک خط:

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

چک کن: حالا بین هر شش کارت — چه کنارِ هم، چه بالا و پایین — دقیقاً ۱۶ پیکسل فاصلهٔ یکنواخت افتاده. دقت کن که gap فقط بین خانه‌ها فاصله می‌گذارد، نه دورِ لبهٔ بیرونیِ grid؛ آن فاصلهٔ بیرونی کارِ paddingِ خودِ .gallery است. عدد 16px را به 4px و بعد 32px عوض کن و ببین grid چطور جمع و باز می‌شود.

۵. در RTL ستون‌ها از راست شروع می‌شوند#

یک نکتهٔ مهم که چون سایتِ ما فارسی و راست‌به‌چپ است باید بدانی: در یک صفحهٔ dir="rtl"، ستون‌های grid هم از راست به چپ جریان می‌گیرند. یعنی «کارت ۱» — اولین کارت در HTML — در گوشهٔ راستِ بالا می‌نشیند، «کارت ۲» سمتِ چپش، و همین‌طور تا چپ. بعد به سطرِ بعد می‌رود و باز از راست شروع می‌کند.

این دقیقاً همان چیزی است که برای یک خوانندهٔ فارسی طبیعی است: چشم از راست شروع می‌کند. grid این را خودش رعایت می‌کند چون به direction صفحه احترام می‌گذارد. اگر همین گالری را در یک صفحهٔ انگلیسیِ dir="ltr" بگذاری، «کارت ۱» به گوشهٔ چپِ بالا می‌رود. تو لازم نیست کاری بکنی — فقط بدان که «ستونِ اول» در فارسی یعنی راست‌ترین ستون. در فصل بعد که بخواهیم کارت‌ها را با شمارهٔ ستون سرِ جای دقیق بگذاریم، این نکته خیلی به کار می‌آید.

💡 نکته: ترتیبِ کارت‌ها در HTML همان ترتیبِ چیده‌شدن در grid است. اگر «کارت ۳» را در کد جابه‌جا کنی، جایش در گالری هم عوض می‌شود. grid ترتیبِ منبع را دنبال می‌کند، مگر بعداً صریح بگویی هر کدام کجا برود (فصل بعد).

۶. grid کِی، flexbox کِی؟#

حالا دو ابزارِ چیدمان داری و سؤالِ درست این است: کدام را کجا؟ جوابْ یک کلمه است — محور.

  • یک محور → flexbox. وقتی چیزها را در یک خط می‌چینی: یک منو، یک ردیفِ دکمه، یک نوارِ بالای صفحه، وسط‌چین‌کردنِ یک چیز. flexbox به محتوا نگاه می‌کند و اندازه‌ها را نرم پخش می‌کند.
  • دو محور → grid. وقتی چیزها باید هم در ستون و هم در سطر تراز بمانند: یک گالری، یک صفحهٔ محصولات، اسکلتِ کلِ یک صفحه. grid اول سطر و ستون را می‌کشد، بعد محتوا را داخلش می‌نشاند.

یک راهِ ساده برای به‌خاطر سپردن: اگر داری چیزها را در امتدادِ هم می‌چینی، flexbox؛ اگر داری یک نقشهٔ سطر-و-ستون می‌سازی، grid. این دو رقیبِ هم نیستند؛ در سایت‌های واقعی کنارِ هم به کار می‌روند — grid برای اسکلتِ بزرگِ صفحه، flexbox برای چیدنِ محتوای داخلِ هر خانه.

مقایسهٔ دو چیدمان کنار هم: سمت راست چند آیتم روی یک خط افقی برای flexbox، سمت چپ یک چیدمانِ منظم از سطر و ستون برای grid

🤖 با AI: از دستیار AI ات بپرس «برای این کار flexbox بهتر است یا grid؟» و یک نمونهٔ واقعی بده (مثلاً «یک نوار منو با پنج لینک» یا «یک گالریِ دوازده‌تایی عکس»). جوابش را با معیارِ خودمان بسنج: چند محور دارد؟ یک خط یا یک grid؟ و مهم‌تر، پیشنهادش را همان‌جا در آزمایشگاه امتحان کن و با چشمت ببین کدام تمیزتر درمی‌آید — AI دربارهٔ layout با اطمینان اشتباه می‌گوید.

کد کاملِ این فصل#

این هم دو فایلِ کامل، یک‌جا. اول index.html:

<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
  <head>
    <meta charset="UTF-8">
    <title>گالری کارت‌ها</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <section class="gallery">
      <article class="card">کارت ۱</article>
      <article class="card">کارت ۲</article>
      <article class="card">کارت ۳</article>
      <article class="card">کارت ۴</article>
      <article class="card">کارت ۵</article>
      <article class="card">کارت ۶</article>
    </section>
  </body>
</html>

و styles.css:

/* styles.css */
* {
  box-sizing: border-box;
}

body {
  background-color: #f6edda;
  margin: 0;
  padding: 24px;
}

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

.card {
  background-color: #2a6b93;
  color: #ffffff;
  padding: 24px;
  border-radius: 8px;
  text-align: center;
}

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

واژه‌های تازهٔ این فصل#

کلمه تلفظ به حروف فارسی یعنی چه
grid گِرید سیستمِ چیدمان در سطر و ستون؛ ابزارِ چیدمانِ دومحوره
display: grid دیسپلی گِرید یک عنصر را به یک grid تبدیل می‌کند
grid-template-columns گِرید تمپلیت کالمنز تعداد و پهنای ستون‌های grid را تعیین می‌کند
fr اِف‌آر (fraction) واحدِ «سهم»؛ فضای خالی را به نسبت بین ستون‌ها پخش می‌کند
gap گَپ فاصلهٔ بین خانه‌های grid، هم ستونی هم سطری

تمرین‌ها

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

در فصل بعد#

الان می‌توانی یک grid بسازی و بگذاری محتوا خودش سرِ جایش بنشیند. ولی گاهی می‌خواهی یک کارتِ خاص دو ستون را با هم بگیرد، یا یک عکس دو سطر را بپوشاند — یعنی خودت دقیقاً بگویی هر چیز کجای grid بنشیند. فصل بعد سراغ همین می‌رویم: با grid-template-rows، grid-column، grid-row و span هر آیتم را سرِ خانهٔ دلخواهش می‌گذاری، و می‌بینی چطور شمارهٔ خط‌ها در RTL از راست شروع می‌شود.

به آخر این فصل رسیدی!

اگر ساختی و جواب داد، این دکمه مال توست.