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

فصل ۶ از ۱۱

پیشرفت ترم
۰٪

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

جای‌گذاری در grid

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

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

آخر این فصل یک «تختهٔ چیدمان» داری: یک مطلبِ ویژه که مثل یک بنرِ بزرگ، دو ستون و دو سطر را با هم می‌گیرد، و دو کارتِ کوچک‌تر که کنارش تر و تمیز جا خوش می‌کنند. تا فصل قبل می‌گذاشتی محتوا خودش سرِ جایش بنشیند؛ اینجا یاد می‌گیری خودت بگویی هر آیتم دقیقاً کجای grid بنشیند — از کدام خط تا کدام خط.

طرح یک چیدمانِ سه‌ستونه با خط‌های شماره‌دار؛ یک بلوکِ بزرگ که دو ستون و دو سطر را می‌پوشاند و دو بلوکِ کوچک کنارش، با خط‌های راهنمای شماره‌دار از راست به چپ

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

  • خط‌های شماره‌دارِ یک grid را بشناسی و در RTL بدانی خط ۱ کجاست
  • با grid-column و grid-row یک آیتم را از یک خط تا خطِ دیگر بکشی
  • با span بگویی یک آیتم چند خانه را بگیرد، بدون شمردنِ خطِ پایان
  • خط‌ها را نام‌دار کنی تا کد خوانا بماند

قبل از شروع#

  • از فصل ۵ (همین ترم): display: grid، grid-template-columns، fr و gap — همان grid را برمی‌داریم و این‌بار آیتم‌ها را دستی جا می‌گذاریم.
  • از فصل ۵: این نکته که در RTL ستون‌ها از راست شروع می‌شوند — اینجا کاملش می‌کنیم.

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

۱. خط‌های grid: شماره‌هایی که همه‌چیز رویشان می‌نشیند#

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

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

پس وقتی می‌گویی «این آیتم از خطِ ۱ تا خطِ ۳»، در فارسی یعنی «از لبهٔ راست تا دو ستون آن‌طرف‌تر». همین را نگه دار؛ الان ازش استفاده می‌کنیم. بیا اول grid را بسازیم. در آزمایشگاه این HTML را بنویس:

<section class="board">
  <article class="tile feature">مطلب ویژه</article>
  <article class="tile">یادداشت</article>
  <article class="tile link">پیوند</article>
</section>

و یک چیدمانِ سه‌ستونه با دو سطرِ ۱۴۰ پیکسلی بساز:

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

.board {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 140px 140px;
  gap: 16px;
}

.tile {
  background-color: #2a6b93;
  color: #ffffff;
  padding: 16px;
  border-radius: 8px;
}

اینجا برای اولین بار grid-template-rows را دیدی: دقیقاً مثل grid-template-columns است ولی برای سطرها. 140px 140px یعنی دو سطر، هر کدام ۱۴۰ پیکسل بلند. تعیینِ بلندیِ سطرها لازم است تا وقتی آیتمی دو سطر را بگیرد، واقعاً بلند و دیدنی شود.

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

۲. grid-column و grid-row: از یک خط تا خطِ دیگر#

می‌خواهیم «مطلب ویژه» یک بنرِ بزرگ شود که دو ستونِ راست و هر دو سطر را بگیرد. برای این کار به آیتم می‌گویی از کدام خط شروع کن و به کدام خط ختم شو. grid-column برای خطوطِ عمودی است و grid-row برای افقی. شکلش این است: شمارهٔ خطِ شروع / شمارهٔ خطِ پایان.

.feature {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
  background-color: #bc3e1c;
}

grid-column: 1 / 3 یعنی «از خطِ عمودیِ ۱ تا خطِ عمودیِ ۳» — که چون در RTL خطِ ۱ سمتِ راست است، یعنی دو ستونِ سمتِ راست. grid-row: 1 / 3 یعنی «از خطِ افقیِ ۱ تا ۳» — یعنی هر دو سطر. رنگش را هم قرمز کردیم تا از بقیه جدا باشد.

چک کن: «مطلب ویژه» حالا یک بلوکِ بزرگِ قرمز است که گوشهٔ راستِ تخته را کامل — دو ستون در دو سطر — پوشانده، و دو کارتِ کوچکِ آبی خودشان رفته‌اند سمتِ چپ. آیتم‌هایی که جای‌گذاریِ صریح ندارند، خودشان اولین خانهٔ خالی را پیدا می‌کنند و می‌نشینند.

⚠️ مواظب باش: شمارهٔ خطِ پایان، خطِ بعد از آخرین ستونی است که می‌خواهی بگیری، نه شمارهٔ خودِ آن ستون. برای گرفتنِ دو ستونِ اول، 1 / 3 می‌نویسی نه 1 / 2. این یکی-اضافه، رایج‌ترین جایی است که تازه‌کارها اشتباه می‌کنند — و همین الان یک نمونه‌اش را می‌سازیم.

۳. یک آیتم که رفت روی آیتمِ دیگر#

بیا کارتِ «پیوند» را هم دستی جا بگذاریم. می‌خواهیم برود خانهٔ پایین-چپ، یعنی ستونِ سومِ (چپ‌ترین) سطرِ دوم. ستونِ سوم بین خطِ ۳ و خطِ ۴ است، پس باید بنویسیم grid-column: 3 / 4. ولی فرض کن حواست پرت شود و بنویسی:

.link {
  grid-column: 2 / 3;
  grid-row: 2 / 3;
}

حالا نگاه کن: کارتِ «پیوند» رفت روی گوشهٔ پایینِ آن بلوکِ قرمزِ ویژه و رویش را پوشاند. دو آیتم توی یک خانه افتاده‌اند و روی هم سوار شده‌اند.

🔧 اگر کار نکرد: این عمدی بود. grid-column: 2 / 3 یعنی «ستونِ دوم» — همان ستونی که آیتمِ ویژه از قبل گرفته بودش. پس دو آیتم توی یک خانه نشستند و چون «پیوند» بعد از «ویژه» در HTML آمده، رویش کشیده شد. برخلافِ جریانِ عادیِ صفحه، آیتم‌های grid می‌توانند هم‌پوشانی کنند و کنار نمی‌روند. رفعش ساده است: ما ستونِ سوم را می‌خواستیم، نه دوم. یک خط جابه‌جا شمردیم. درستش کن:

.link {
  grid-column: 3 / 4;
  grid-row: 2 / 3;
}

چک کن: حالا «پیوند» رفت سرِ جای درستش، خانهٔ پایین-چپ، و دیگر هیچ‌چیز روی هم نیست. «یادداشت» هم خودش خانهٔ بالا-چپ را گرفته. این درسِ مهمِ جای‌گذاری است: یک خط اشتباه، و دو چیز توی یک خانه می‌افتند. همیشه از خطِ ۱ (در RTL: سمتِ راست) بشمار و یادت باشد خطِ پایان یکی جلوتر از ستونِ آخر است.

۴. span: بگو چند خانه، نه تا کدام خط#

شمردنِ خطِ پایان همیشه دردسر است، مخصوصاً وقتی grid بزرگ می‌شود. یک راهِ راحت‌تر هست: به‌جای خطِ پایان بگو چند خانه را بگیرد، با کلمهٔ span. مثلاً آیتمِ ویژه را که دو ستون می‌خواستیم، این‌طور هم می‌شود نوشت:

.feature {
  grid-column: 1 / span 2;
  grid-row: 1 / span 2;
  background-color: #bc3e1c;
}

1 / span 2 یعنی «از خطِ ۱ شروع کن و دو ستون جلو برو». نتیجه دقیقاً همان 1 / 3 است، ولی این‌بار لازم نبود خطِ پایان را حساب کنی؛ فقط گفتی چند تا. این وقتی طلاست که grid شلوغ است و شمردنِ خط‌ها سخت می‌شود.

چک کن: روی صفحه هیچ فرقی نمی‌بینی — بلوکِ ویژه هنوز همان دو-در-دویِ قرمز است. این خودش نکته است: 1 / 3 و 1 / span 2 دو راهِ نوشتنِ یک چیزند. هرکدام خوانا‌تر بود همان را به‌کار ببر.

۵. خط‌های نام‌دار: کد را خوانا کن#

grid-column: 1 / 3 کار می‌کند، ولی سه ماه بعد که برگردی، «۱» و «۳» چه معنایی دارند؟ grid می‌گذارد به خط‌ها اسم بدهی، تا کد خودش خودش را توضیح دهد. اسم‌ها را داخل [ ] سرِ جای هر خط در grid-template-columns می‌نویسی:

.board {
  display: grid;
  grid-template-columns: [edge-r] 1fr [col-a] 1fr [col-b] 1fr [edge-l];
  grid-template-rows: 140px 140px;
  gap: 16px;
}

حالا خطِ راست‌ترین اسمش edge-r است، خطِ چپ‌ترین edge-l، و دو خطِ میانی col-a و col-b. به‌جای عدد، اسم را به‌کار ببر:

.feature {
  grid-column: edge-r / col-b;
  grid-row: 1 / 3;
  background-color: #bc3e1c;
}

.link {
  grid-column: col-b / edge-l;
  grid-row: 2 / 3;
}

چک کن: چیدمان مو به مو مثل قبل است، ولی حالا کد را که می‌خوانی می‌فهمی چه خبر است: «ویژه از لبهٔ راست تا خطِ col-b». اسم‌ها دلبخواهی‌اند — هر اسمی که برایت معنا دارد بگذار، فقط انگلیسی و بدون فاصله. برای layout های بزرگ، خطِ نام‌دار تفاوتِ بینِ کدِ قابل‌فهم و کدِ پُر از عددِ گیج‌کننده است.

🤖 با AI: یک grid با چند آیتمِ جای‌گذاری‌شده به دستیار AI ات بده و بپرس «این آیتم چرا روی آن یکی افتاده؟». ولی اول خودت خط‌ها را بشمار و حدس بزن؛ بعد جوابِ AI را با آن بسنج. در RTL، AI اغلب فراموش می‌کند خطِ ۱ سمتِ راست است و جواب را برعکس می‌دهد — این خودش بهترین تمرینِ «AI هم اشتباه می‌کند» است. با چیزی که در آزمایشگاه می‌بینی چک کن.

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

اول 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="board">
      <article class="tile feature">مطلب ویژه</article>
      <article class="tile">یادداشت</article>
      <article class="tile link">پیوند</article>
    </section>
  </body>
</html>

و styles.css:

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

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

.board {
  display: grid;
  grid-template-columns: [edge-r] 1fr [col-a] 1fr [col-b] 1fr [edge-l];
  grid-template-rows: 140px 140px;
  gap: 16px;
}

.tile {
  background-color: #2a6b93;
  color: #ffffff;
  padding: 16px;
  border-radius: 8px;
}

.feature {
  grid-column: edge-r / col-b;
  grid-row: 1 / 3;
  background-color: #bc3e1c;
}

.link {
  grid-column: col-b / edge-l;
  grid-row: 2 / 3;
}

چک کن: یک بلوکِ بزرگِ قرمزِ ویژه در سمتِ راست که دو ستون و دو سطر را گرفته، و دو کارتِ آبی مرتب در ستونِ چپ. هیچ آیتمی روی آیتمِ دیگر نیست.

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

کلمه تلفظ به حروف فارسی یعنی چه
grid line گِرید لاین خطِ شماره‌دارِ بینِ ستون‌ها و سطرها؛ در RTL خطِ ۱ سمتِ راست است
grid-template-rows گِرید تمپلیت روز تعداد و بلندیِ سطرهای grid را تعیین می‌کند
grid-column گِرید کالمن آیتم را از یک خطِ عمودی تا خطِ عمودیِ دیگر می‌کشد
grid-row گِرید رو آیتم را از یک خطِ افقی تا خطِ افقیِ دیگر می‌کشد
span اِسپَن «چند خانه بگیر»؛ جای‌گزینِ نوشتنِ خطِ پایان

تمرین‌ها

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

در فصل بعد#

الان می‌توانی هر آیتم را تک‌به‌تک سرِ جایش بگذاری. ولی برای یک صفحهٔ کامل — با سرصفحه، منو، محتوای اصلی، ستونِ کناری و پاصفحه — شمردنِ خط برای هر ناحیه خسته‌کننده می‌شود. فصل بعد یک راهِ خیلی خواناتر یاد می‌گیری: با grid-template-areas نقشهٔ صفحه را مثل یک نقاشیِ ساده می‌کشی و به هر ناحیه یک اسم می‌دهی. کنارش repeat()، minmax() و auto-fit را می‌بینی که یک گالری را بدون هیچ عددِ ثابتی responsive می‌کنند.

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

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