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

فصل ۷ از ۱۱

پیشرفت ترم
۰٪

ترم ۲ · CSS: کنترل ظاهر

جریان عادی صفحه

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

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

آخر این فصل یک صفحهٔ کوچکِ یادداشت داری، ولی چیزی که واقعاً به‌دست می‌آوری فهمِ این است که مرورگر چطور عناصر را می‌چیند. چرا دو پاراگراف زیر هم می‌آیند ولی چند لینک کنار هم؟ چطور یک لینک را وادار کنی مثل یک دکمهٔ پهن رفتار کند؟ و آن غافلگیریِ عجیب که وقتی به دو جعبه margin می‌دهی، فاصله‌شان کمتر از چیزی می‌شود که انتظار داشتی — از کجا می‌آید؟ این فصل همهٔ این‌ها را روشن می‌کند.

مقایسهٔ دو نوع چیدمان: در سمتی چند جعبهٔ پهن که کاملاً زیر هم چیده شده‌اند (block)، در سمتِ دیگر چند جعبهٔ کوچک که در یک خط کنار هم نشسته‌اند (inline)

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

  • فرقِ عناصرِ block و inline را در جریانِ عادیِ صفحه توضیح بدهی
  • با display رفتارِ یک عنصر را عوض کنی، از جمله inline-block و none
  • بگویی margin collapsing چیست و چرا فاصله‌ها را کمتر از انتظار می‌کند
  • با direction جهتِ چیدمان را برای فارسی و بخش‌های لاتین تنظیم کنی

قبل از شروع#

  • از فصل ۴: margin، padding، width و box-sizing.
  • از فصل ۶: text-align و font-family.
  • از فصل ۱: background-color — رنگ به جعبه‌ها می‌دهیم تا مرزهایشان را ببینیم.

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

۱. جریان عادی: block و inline#

مرورگر هر عنصری را به یکی از دو شکل می‌چیند، و این را displayِ پیش‌فرضِ آن عنصر تعیین می‌کند:

  • عناصرِ block: هرکدام یک خطِ کاملِ خودشان را می‌گیرند، تا کلِ عرضِ در دسترس کشیده می‌شوند، و زیرِ هم می‌آیند. <p>، <h1>، <article> و <div> همه block اند.
  • عناصرِ inline: فقط به‌اندازهٔ محتوایشان جا می‌گیرند و در همان خط، کنارِ هم می‌نشینند. <a>، <strong> و <em> inline اند.

بیا ببینیمش. اول به صفحه یک پایهٔ ساده بده و دو یادداشت بساز:

body {
  font-family: Tahoma, sans-serif;
  background-color: #f6edda;
  padding: 24px;
}

.note {
  background-color: #cfe3f3;
  padding: 16px;
}

هر یادداشت یک <article class="note"> است. چون <article> عنصری block است، دو یادداشت زیرِ هم می‌آیند و هرکدام تا کلِ عرض کشیده می‌شوند — رنگِ آبیِ ملایمشان این را نشان می‌دهد.

حالا چند برچسب هم اضافه کن که لینک‌اند (inline):

.tags a {
  background-color: #2a6b93;
  color: #ffffff;
  padding: 4px 10px;
}

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

قبل از ادامه، جواب بده: چرا سه برچسب کنارِ هم می‌نشینند ولی دو یادداشت زیرِ هم؟ (چون برچسب‌ها <a> و inline اند، ولی یادداشت‌ها <article> و block — و displayِ پیش‌فرضشان این چیدمان را تعیین می‌کند.)

۲. عوض‌کردنِ display#

با property ‌ی display می‌توانی رفتارِ پیش‌فرضِ یک عنصر را عوض کنی. بیایید یک لینک را به یک دکمهٔ پهن تبدیل کنیم. یک لینکِ «برو به بالا» بساز و بخواه پهنایش ۲۰۰ پیکسل باشد:

.button {
  width: 200px;
  background-color: #a36207;
  color: #ffffff;
  padding: 10px;
  text-align: center;
}

به صفحه نگاه کن: پس‌زمینهٔ نارنجی فقط دورِ متن است و آن width: 200px اثری نکرد. دلیلش این است که <a> عنصری inline است، و عناصرِ inline width و height را نادیده می‌گیرند — فقط به‌اندازهٔ محتوایشان جا می‌گیرند، هرچه بگویی.

راهِ حل display: inline-block است: عنصر در خط می‌ماند (مثل inline) ولی width و height را می‌پذیرد (مثل block). به دکمه اضافه‌اش کن:

.button {
  display: inline-block;
  width: 200px;
  background-color: #a36207;
  color: #ffffff;
  padding: 10px;
  text-align: center;
}

چک کن: حالا دکمه دقیقاً ۲۰۰ پیکسل پهن است و متنش وسط‌چین. مقدارِ display را به inline برگردان و ببین دوباره جمع می‌شود؛ به block عوضش کن و ببین یک خطِ کامل می‌گیرد و پهنایش را نگه می‌دارد ولی دیگر چیزی کنارش نمی‌نشیند. سه رفتار، سه display.

یک مقدارِ مهمِ دیگرِ display هم none است: عنصر را کاملاً از صفحه برمی‌دارد، انگار اصلاً وجود ندارد. برای یادداشتی که هنوز آماده نیست:

.draft {
  display: none;
}

چک کن: یادداشتِ draft کلاً ناپدید شد و جای خالی هم نگذاشت — چون display: none عنصر را از جریان بیرون می‌اندازد، نه اینکه فقط نامرئی‌اش کند.

⚠️ مواظب باش: display: none عنصر را از دیدِ screen reader ها هم پنهان می‌کند، نه فقط از چشم. پس برای محتوایی که باید خوانده شود ولی موقتاً دیده نشود از آن استفاده نکن؛ display: none یعنی «این اصلاً اینجا نیست»، برای همه — چه چشم، چه ماشین.

۳. یک غافلگیری در فاصله‌ها: margin collapsing#

حالا می‌خواهیم بین دو یادداشت فاصله بگذاریم. طبیعی است که به هر یادداشت از بالا و پایین margin بدهی. این را امتحان کن:

.note {
  background-color: #cfe3f3;
  padding: 16px;
  margin-top: 48px;
  margin-bottom: 48px;
}

حالا فکر کن: یادداشتِ اول 48px margin از پایین دارد، و یادداشتِ دوم 48px margin از بالا. این دو margin به‌هم می‌رسند، پس انتظار داری فاصلهٔ بینشان 48 + 48 = 96 پیکسل باشد. ولی به صفحه نگاه کن و اندازه بگیر — فاصله فقط 48 است، نصفِ چیزی که انتظار داشتی.

🔧 اگر کار نکرد: این عمدی است و یکی از معروف‌ترین غافلگیری‌های CSS است، به‌نامِ margin collapsing. وقتی margin ‌ی عمودیِ دو جعبهٔ block به‌هم می‌رسند، در هم فرو می‌روند و به یک margin تبدیل می‌شوند — و اندازه‌اش بزرگ‌ترِ آن دو است، نه جمعشان. اینجا هر دو 48 بودند، پس نتیجه 48 شد. اگر یکی 48 و دیگری 24 بود، باز هم 48 می‌شد (بزرگ‌تره)، نه 72. این خرابی نیست؛ عمداً این‌طور طراحی شده تا وقتی چند پاراگرافِ پشتِ‌هم margin دارند، فاصله‌هاشان دوبرابر و ناجور نشود.

پس چطور فاصله‌ها را قابلِ‌پیش‌بینی کنیم؟ ساده‌ترین عادت این است که فاصله را فقط از یک طرف بدهی. مثلاً همیشه margin-bottom بگذار و margin-top را صفر کن؛ آن‌وقت هیچ‌وقت دو margin رو‌به‌روی هم قرار نمی‌گیرند که بخواهند collapse کنند:

.note {
  background-color: #cfe3f3;
  padding: 16px;
  margin-top: 0;
  margin-bottom: 24px;
}

چک کن: حالا بینِ دو یادداشت دقیقاً 24 پیکسل فاصله است، همان‌قدر که خواستی — چون فقط یک margin آنجاست، نه دو تا. مقدارِ margin-bottom را به 40 عوض کن و ببین فاصله دقیقاً 40 می‌شود، بدونِ هیچ غافلگیری‌ای. یک طرف، یک عدد، یک نتیجه.

💡 نکته: فقط margin ‌های عمودی (بالا و پایین) collapse می‌کنند. margin ‌های افقی (چپ و راست) هیچ‌وقت در هم فرو نمی‌روند — دو جعبهٔ کنارِ هم با margin افقی، فاصله‌شان همیشه جمعِ دو margin است.

۴. direction: جهتِ صفحه برای فارسی#

فارسی از راست به چپ نوشته می‌شود. تا حالا صفحه‌هایمان <html lang="fa" dir="rtl"> داشتند، و همان dir="rtl" است که به مرورگر می‌گوید همه‌چیز را از راست بچیند. معادلِ همین کار در CSS، property ‌ی direction است: rtl (راست‌به‌چپ) یا ltr (چپ‌به‌راست).

معمولاً dir="rtl"ِ روی <html> کافی است و کلِ صفحه را درست می‌کند. ولی گاهی یک تکهٔ کوچکِ لاتین داری — یک آدرسِ سایت، یک تکه کدِ انگلیسی — که باید چپ‌به‌راست باشد وگرنه علامت‌هایش جابه‌جا دیده می‌شوند. برای همان تکه direction: ltr می‌گذاری:

.ltr {
  direction: ltr;
  text-align: left;
}

چک کن: خطِ MDN: developer.mozilla.org حالا از چپ شروع می‌شود و ترتیبِ درست دارد. مقدارِ direction را به rtl عوض کن و ببین چطور دو‌نقطه و بخش‌های آدرس جابه‌جا و بد دیده می‌شوند — همان اشتباهی که وقتی جهت را برای متنِ لاتین درست نگذاری پیش می‌آید.

🤖 با AI: یک تکه متنِ فارسی که وسطش یک عدد یا یک کلمهٔ انگلیسی دارد را به دستیار AI ات بده و بپرس «چرا این علامت یا عدد جابه‌جا دیده می‌شود و با direction چطور درستش کنم؟». جوابش را در آزمایشگاه امتحان کن — این دقیقاً همان جور مشکلی است که دیدنش در مرورگر صد برابر روشن‌تر از خواندنِ توضیح است.

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

این هم دو فایلِ کامل. اول 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>
    <h1 id="top">یادداشت‌های من</h1>

    <article class="note">
      <p>جعبه‌ها به‌طور عادی زیر هم می‌آیند؛ به این می‌گویند جریان عادی.</p>
    </article>

    <article class="note">
      <p>فاصلهٔ بین دو یادداشت را خودمان و با یک قاعده تعیین کرده‌ایم.</p>
    </article>

    <p class="tags">
      <a href="#top">html</a>
      <a href="#top">css</a>
      <a href="#top">layout</a>
    </p>

    <a class="button" href="#top">برو به بالای صفحه</a>

    <p class="ltr">MDN: developer.mozilla.org</p>

    <p class="draft">این یادداشت هنوز آماده نیست و روی صفحه دیده نمی‌شود.</p>
  </body>
</html>

و styles.css:

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

body {
  font-family: Tahoma, sans-serif;
  background-color: #f6edda;
  padding: 24px;
}

.note {
  background-color: #cfe3f3;
  padding: 16px;
  margin-top: 0;
  margin-bottom: 24px;
}

.tags a {
  background-color: #2a6b93;
  color: #ffffff;
  padding: 4px 10px;
}

.button {
  display: inline-block;
  width: 200px;
  background-color: #a36207;
  color: #ffffff;
  padding: 10px;
  text-align: center;
}

.ltr {
  direction: ltr;
  text-align: left;
}

.draft {
  display: none;
}

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

کلمه تلفظ به حروف فارسی یعنی چه
normal flow نُرمال فلو چیدمانِ پیش‌فرضِ مرورگر بدونِ هیچ دستورِ اضافه
display دیسپلی تعیین می‌کند عنصر block باشد یا inline یا …
block بلاک عنصری که کلِ خط را می‌گیرد و زیرِ هم می‌آید
inline این‌لاین عنصری که در خط، کنارِ بقیه می‌نشیند
inline-block این‌لاین‌بلاک در خط می‌ماند ولی width و height را می‌پذیرد
none نان مقدارِ display که عنصر را کاملاً از صفحه برمی‌دارد
margin collapsing مارجین کُلَپسینگ در هم فرو رفتنِ دو margin عمودیِ مجاور به بزرگ‌ترشان
direction دایرکشِن جهتِ چیدمان: rtl راست‌به‌چپ، ltr چپ‌به‌راست

تمرین‌ها

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

در فصل بعد#

الان می‌دانی مرورگر عناصر را چطور در جریانِ عادی می‌چیند و چطور با display و direction مهارش کنی. تا اینجا جعبه‌ها ساده بودند: یک رنگ، یک قاب. فصل بعد سراغِ زیباسازیِ همین جعبه‌ها می‌رویم: تصویرِ پس‌زمینه، گوشه‌های گِرد با border-radius، سایه با box-shadow، و gradient — چیزهایی که کارت‌ها و دکمه‌هایت را از ساده به حرفه‌ای می‌برند.

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

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