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

فصل ۲ از ۱۱

پیشرفت ترم
۰٪

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

flexbox: یک محور

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

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

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

طرح‌وارهٔ دو محور در flexbox: سه کارت در یک ردیف، یک پیکانِ افقی به‌عنوان main axis که در امتدادِ کارت‌ها می‌رود و یک پیکانِ عمودی به‌عنوان cross axis که عمود بر آن است

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

  • با display: flex روی یک جعبهٔ والد، بچه‌هایش را در یک ردیف کنارِ هم بچینی
  • main axis و cross axis را از هم تشخیص بدهی و بگویی هرکدام کدام طرف است
  • با flex-direction جهتِ ردیف را بین افقی و عمودی عوض کنی
  • با gap فاصلهٔ بینِ کارت‌ها را تمیز و بدونِ هک تنظیم کنی

قبل از شروع#

  • از فصل ۱: جریانِ عادی و اینکه چرا block ها زیرِ هم می‌چینند — flexbox دقیقاً همان را عوض می‌کند.
  • از فصل ۱: محورِ inline در RTL از راست به چپ می‌رود — همین‌جا دوباره لازمش داریم.
  • از ترم ۲ فصل ۲: selector کلاس (.cards) — به جعبهٔ والد با کلاسش استایل می‌دهیم.

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

۱. یک ردیف کارت، هنوز زیرِ هم#

بیا سه کارتِ ساده بسازیم. یک جعبهٔ والد که همه را در بر می‌گیرد، و سه جعبهٔ کوچک تویش:

<main class="cards">
  <div class="card">۱</div>
  <div class="card">۲</div>
  <div class="card">۳</div>
</main>

والد را <main> گذاشتیم چون این کارت‌ها کلِ محتوای اصلیِ این صفحهٔ کوچک‌اند — یادت هست از ترم ۱ که <main> یعنی محتوای اصلیِ صفحه. ولی خودِ کارت‌ها <div> هستند، و این‌بار درست است: در ترم ۱ گفتیم <div> آخرین انتخاب است، فقط وقتی هیچ tag معناداری نمی‌خورد و تنها به یک جعبه برای چیدمان نیاز داری. این کارت‌ها معنایی ندارند، فقط قرار است چیده شوند؛ وقتی محتوای واقعی داشته باشند (یک محصول، یک مطلب) سراغِ <article> می‌روی. و یک نکتهٔ مهم: display: flex روی هر عنصرِ block کار می‌کند، فرقی نمی‌کند <main> باشد یا <div> — مهم فقط این است که والد باشد.

حالا یک CSS بده تا کارت‌ها دیده شوند:

.cards {
  padding: 16px;
}

.card {
  padding: 24px;
  background-color: #2a6b93;
  color: #ffffff;
  font-size: 24px;
}

چک کن: سه کارتِ آبی می‌بینی که زیرِ هم چیده شده‌اند — چون <div> یک عنصرِ block است و block ها، همان‌طور که فصل قبل دیدیم، روی هم می‌چینند. حالا این را عوض می‌کنیم.

۲. display: flex — و یک اشتباهِ خیلی رایج#

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

.card {
  display: flex;
  padding: 24px;
  background-color: #2a6b93;
  color: #ffffff;
  font-size: 24px;
}

نگاه کن: هیچ اتفاقی نیفتاد. کارت‌ها هنوز عینِ قبل زیرِ هم‌اند.

🔧 اگر کار نکرد: بله، عمدی است. display: flex را روی جای اشتباه گذاشتی. قانون این است: flex روی جعبهٔ والد می‌نشیند، نه روی بچه‌ها — و آن والد، بچه‌های مستقیمِ خودش را کنارِ هم می‌چیند. وقتی به .card دادی‌اش، به هر کارت گفتی «محتوای داخلِ خودت را flex کن»؛ ولی داخلِ هر کارت فقط یک عدد است، پس چیزی برای چیدن نبود و هیچ تغییری ندیدی. جای درست، .cards است — والدی که سه کارت بچه‌اش هستند.

خطِ display: flex را از .card بردار و به .cards بده:

.cards {
  display: flex;
  padding: 16px;
}

چک کن: حالا سه کارت در یک ردیف کنارِ هم نشسته‌اند. همین یک خط، جعبهٔ والد را به یک flex container تبدیل کرد و بچه‌هایش شدند flex item. این مهم‌ترین جملهٔ کلِ ترم است: flexbox را همیشه روی والد می‌گذاری تا بچه‌هایش را بچیند.

💡 نکته: یک راهِ ساده برای اینکه یادت نرود: flex روی «ظرف» است، نه روی «چیزهای داخلِ ظرف». ظرف تصمیم می‌گیرد محتوایش چطور چیده شود.

۳. دو محور: main axis و cross axis#

حالا که کارت‌ها در یک ردیف‌اند، باید یک مدلِ ذهنی برداری که تا آخرِ ترم همراهت است: هر flex container دو محور دارد.

  • main axis — محورِ اصلی، همان جهتی که flex item ها در امتدادش کنارِ هم می‌چینند. الان که کارت‌ها افقی‌اند، main axis افقی است.
  • cross axis — محورِ عرضی، که همیشه عمود بر main axis است. الان که main axis افقی است، cross axis عمودی است.

چرا این مهم است؟ چون در فصل بعد هر دستوری که برای چیدن و وسط‌چین‌کردن یاد می‌گیری، یا روی main axis کار می‌کند یا روی cross axis. اگر این دو را قاطی کنی، دستور روی محورِ اشتباه اثر می‌گذارد و گیج می‌شوی. پس همین حالا محکمش کن.

قبل از ادامه، جواب بده: اگر main axis افقی باشد، cross axis کدام طرف است؟ (جواب: عمودی — چون cross axis همیشه عمود بر main axis است.)

۴. main axis در RTL: چرا کارتِ ۱ سمتِ راست است#

به ردیفت دقت کن: کارتِ ۱ کجاست؟ سمتِ راست. این تصادفی نیست و همان درسِ فصلِ قبل است. جهتِ پیش‌فرضِ main axis از direction صفحه پیروی می‌کند، و صفحهٔ ما RTL است — پس main axis از راست به چپ می‌رود. برای همین اولین کارت سمتِ راست می‌نشیند و بقیه به‌سمتِ چپ می‌آیند. این دقیقاً همان جریانِ inlineای است که فصل قبل دیدی، حالا برای کارت‌ها.

این را با flex-direction می‌بینی. تا حالا مقدارِ پیش‌فرضش که row است کار می‌کرد؛ حالا صریح بنویسش و بعد برعکسش کن:

.cards {
  display: flex;
  flex-direction: row;
  padding: 16px;
}

row یعنی «ردیفِ افقی، در جهتِ صفحه». حالا مقدارش را به row-reverse عوض کن:

.cards {
  display: flex;
  flex-direction: row-reverse;
  padding: 16px;
}

چک کن: با row-reverse ترتیب برعکس شد و حالا کارتِ ۱ رفت سمتِ چپ. پس flex-direction جهتِ main axis را کنترل می‌کند. برای صفحهٔ فارسیِ ما row تقریباً همیشه همان چیزی است که می‌خواهی؛ فقط بدان که «از راست شروع می‌شود» یک اشتباه نیست، رفتارِ درستِ RTL است.

۵. flex-direction: column — همان محور، عمودی‌شده#

flex-direction یک مقدارِ خیلی پرکاربردِ دیگر هم دارد: column. با این، main axis می‌شود عمودی و کارت‌ها دوباره زیرِ هم می‌چینند — ولی این‌بار به‌عنوان flex item، نه جریانِ عادی. امتحانش کن:

.cards {
  display: flex;
  flex-direction: column;
  padding: 16px;
}

چک کن: کارت‌ها دوباره زیرِ هم‌اند، ولی این‌بار main axis عمودی است و cross axis افقی — یعنی دو محور دقیقاً جایشان عوض شد. چرا این با جریانِ عادی فرق دارد؟ چون حالا این جعبه یک flex container است و در فصل بعد می‌توانی همین ستونِ عمودی را با یک خط وسطِ صفحه بیاوری — کاری که با block معمولی سخت بود. فعلاً column را نگه دار یا به row برگردان؛ هر دو را در فصل بعد به‌کار می‌گیریم.

مقایسهٔ flex-direction: در حالتِ row سه کارت در یک ردیفِ افقی، در حالتِ column همان سه کارت در یک ستونِ عمودی، با پیکانِ main axis که در هر حالت جهتش عوض شده

۶. gap — فاصلهٔ تمیز بینِ کارت‌ها#

کارت‌ها الان به هم چسبیده‌اند. در فصل قبل دیدی که فاصله‌انداختن با margin بینِ عنصرهای کنارِ هم می‌تواند دردسر بسازد. flexbox یک ابزارِ مخصوصِ همین کار دارد که تمیزتر است: gap. فقط بینِ item ها فاصله می‌اندازد، نه قبلِ اولی و نه بعدِ آخری. به row برگرد و gap اضافه کن:

.cards {
  display: flex;
  flex-direction: row;
  gap: 16px;
  padding: 16px;
}

چک کن: حالا بینِ هر دو کارت ۱۶ پیکسل فاصله افتاد، ولی دو طرفِ کلِ ردیف نه. مقدارِ gap را به 4px عوض کن و ببین کارت‌ها به هم نزدیک می‌شوند، بعد 40px بگذار و ببین از هم باز می‌شوند. این تمیزترین راهِ فاصله‌گذاری بینِ flex item هاست و از این به بعد همیشه از همین استفاده می‌کنیم.

🤖 با AI: از دستیارِ AI ات بپرس «فرقِ gap و margin برای فاصله‌گذاری بینِ آیتم‌های flex چیست؟». جوابش را با چیزی که همین الان دیدی بسنج: با gap دو طرفِ کلِ ردیف فاصله می‌گیرد یا نه؟ اگر AI چیزی گفت که با چشمت جور درنمی‌آید، به چشمت اعتماد کن، نه به AI.

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

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

<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
  <head>
    <meta charset="UTF-8">
    <title>flexbox: یک محور</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <main class="cards">
      <div class="card">۱</div>
      <div class="card">۲</div>
      <div class="card">۳</div>
    </main>
  </body>
</html>

و styles.css:

/* styles.css */
.cards {
  display: flex;
  flex-direction: row;
  gap: 16px;
  padding: 16px;
}

.card {
  padding: 24px;
  background-color: #2a6b93;
  color: #ffffff;
  font-size: 24px;
}

چک کن: روی صفحه سه کارتِ آبی در یک ردیف با فاصلهٔ منظم می‌بینی که از راست شروع می‌شوند. display: flex روی والد، flex-direction: row برای جهت، و gap برای فاصله — همین سه، پایهٔ هر چیزی است که در فصل‌های بعد رویش می‌سازیم.

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

کلمه تلفظ به حروف فارسی یعنی چه
flexbox فلکس‌باکس روشِ چیدنِ بچه‌های یک جعبه در یک محور
display: flex دیسپلی فلکس خطی که جعبهٔ والد را به flex container تبدیل می‌کند
flex container فلکس کانتینر جعبهٔ والدی که display: flex گرفته
flex item فلکس آیتم هر بچهٔ مستقیمِ یک flex container
main axis مِین اَکسیس محورِ اصلی که آیتم‌ها در امتدادش می‌چینند
cross axis کراس اَکسیس محورِ عمود بر main axis
flex-direction فلکس‌دایرکشن جهتِ main axis: row / row-reverse / column
gap گَپ فاصلهٔ بینِ آیتم‌ها، فقط بینشان

تمرین‌ها

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

در فصل بعد#

الان می‌توانی هر مجموعه‌ای را در یک ردیف یا ستون بچینی و فاصله‌شان را کنترل کنی. ولی هنوز کاری با جای کارت‌ها در طولِ ردیف نکرده‌ای — همه سرِ شروعِ محور چسبیده‌اند. فصل بعد دقیقاً همین است: با justify-content آیتم‌ها را در امتدادِ main axis پخش می‌کنی (وسط، دو سر، با فاصلهٔ برابر) و با align-items روی cross axis می‌چینی‌شان — و بالاخره به آن چیزی می‌رسی که هر تازه‌کاری آرزویش را دارد: وسط‌چینِ واقعیِ عمودی.

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

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