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

فصل ۸ از ۱۱

پیشرفت ترم
۰٪

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

position

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

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

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

مقایسهٔ پنج حالتِ position روی یک عنصرِ یکسان: عادی سرِ جایش، کمی جابه‌جا شده، چسبیده به گوشهٔ یک جعبه، چسبیده به گوشهٔ کلِ صفحه، و چسبیده به بالای صفحه هنگام اسکرول

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

  • فرقِ static، relative، absolute، fixed و sticky را بگویی و هرکدام را به‌جا به‌کار ببری
  • یک عنصر را از جریانِ عادیِ صفحه بیرون بکشی و دقیقاً یک‌جای مشخص بگذاری‌اش
  • بگویی containing block چیست و چرا یک عنصرِ absolute گاهی به گوشهٔ اشتباه می‌پرد
  • یک سرصفحهٔ چسبان و یک دکمهٔ همیشه‌ماندگار بسازی

قبل از شروع#

  • از ترم ۲: border، border-radius، background-color و font-size با rem — کارت‌ها و برچسب‌ها را باهاشان خوش‌فرم می‌کنیم.
  • از ترم ۱: <header>، <main>، <article> و <button> — اسکلتِ فروشگاه از همین‌ها ساخته می‌شود.

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

۱. static و relative: جای عادی، و یک تکانِ کوچک#

هر چیزی که تا این فصل ساختی، position: static بود — این مقدارِ پیش‌فرضِ همهٔ عنصرهاست. static یعنی «سرِ جای عادی‌ات در جریانِ صفحه بمان»؛ همان چیدمانی که تا حالا دیدی. بیا اسکلتِ فروشگاه را بسازیم. در آزمایشگاه این HTML را بنویس:

<header class="topbar">فروشگاه من</header>

<main>
  <article class="card">
    <h2>هدفون بی‌سیم</h2>
    <p>صدای شفاف و باتری طولانی.</p>
  </article>
  <article class="card">
    <h2>کیبورد مکانیکی</h2>
    <p>تایپ سریع و لمس دقیق.</p>
  </article>
</main>

و یک استایلِ ساده:

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

.topbar {
  background-color: #2a6b93;
  color: #ffffff;
  padding: 16px;
}

.card {
  background-color: #ffffff;
  border: 2px solid #2a6b93;
  border-radius: 8px;
  padding: 24px;
  margin: 16px;
}

چک کن: یک نوارِ آبی در بالا و زیرش دو کارتِ سفیدِ قاب‌دار می‌بینی، پشتِ‌سرِ هم. این جریانِ عادی است — همه static.

حالا relative. این مقدار می‌گوید «سرِ جای عادی‌ات بمان، ولی بعد یک تکانِ کوچک از همان‌جا بخور». با top، left، right و bottom می‌گویی چقدر تکان بخورد. یک کارت را موقتاً این‌طور امتحان کن:

.card {
  position: relative;
  top: 20px;
  left: 20px;
}

چک کن: کارت‌ها ۲۰ پیکسل به پایین و ۲۰ پیکسل به چپ جابه‌جا شدند — ولی جای خالیِ قبلی‌شان سرِ جایش ماند و بقیه هیچ تکانی نخوردند. این نکتهٔ کلیدیِ relative است: عنصر از جای خودش نسبت به خودش جابه‌جا می‌شود، اما فضایی که اشغال کرده بود همان‌جا رزرو می‌ماند.

این تکان‌دادن کاربردِ روزمرهٔ زیادی ندارد. قدرتِ اصلیِ relative چیزِ دیگری است که همین الان لازمش می‌شویم: یک عنصرِ relative تبدیل می‌شود به یک لنگر برای فرزندانش. برای همین آن top و left را پاک کن و فقط position: relative را نگه دار — چرایش را در بخشِ بعد می‌بینی.

۲. absolute: از جریان بیرون بیا#

می‌خواهیم روی گوشهٔ اولین کارت یک برچسبِ «جدید» بچسبانیم. برای این کار به یک رفتارِ تازه نیاز داریم: position: absolute. برخلافِ relative، این مقدار عنصر را کاملاً از جریان بیرون می‌کشد — انگار دیگر آنجا نیست، فضایی هم اشغال نمی‌کند — و بعد می‌گذاردش سرِ مختصاتی که با top/right/bottom/left می‌دهی.

اول در HTML، داخلِ اولین کارت و بالای <h2>، برچسب را اضافه کن:

<article class="card">
  <div class="badge">جدید</div>
  <h2>هدفون بی‌سیم</h2>
  <p>صدای شفاف و باتری طولانی.</p>
</article>

و برچسب را absolute کن و به گوشهٔ بالا-راست بفرست. مقدارهای منفی کمی بیرونش می‌کشند تا مثل یک برچسبِ چسبانده‌شده روی گوشه دیده شود:

.badge {
  position: absolute;
  top: -10px;
  right: -10px;
  background-color: #bc3e1c;
  color: #ffffff;
  padding: 4px 12px;
  border-radius: 999px;
}

حالا نگاه کن: برچسبِ «جدید» به‌جای گوشهٔ کارت، پرید به گوشهٔ بالا-راستِ کلِ صفحه و آنجا، بالای نوارِ فروشگاه، نشست!

۳. containing block: چرا برچسب به گوشهٔ اشتباه پرید#

اینجا مهم‌ترین تلهٔ کلِ این فصل است، و ارزشِ آن را دارد که آرام بخوانی.

🔧 اگر کار نکرد: این عمدی بود. سؤال این است: وقتی می‌گویی «برو به بالا-راست»، یعنی بالا-راستِ چی؟ یک عنصرِ absolute مختصاتش را نسبت به نزدیک‌ترین جدِّ خودش می‌سنجد که position اش static نباشد — یعنی جدّی که relative، absolute، fixed یا sticky باشد. به این جدّ می‌گویند containing block. برچسبِ ما هیچ‌کدام از جدهایش (کارت، main، body) هنوز position دار نبودند، پس مرورگر آخرین گزینه را برداشت: خودِ صفحه. برای همین برچسب به گوشهٔ صفحه پرید، نه گوشهٔ کارت.

رفعش دقیقاً همان کاری است که در بخش ۱ زمینه‌اش را چیدیم: کارت را relative کن تا بشود containing blockِ برچسب:

.card {
  position: relative;
  background-color: #ffffff;
  border: 2px solid #2a6b93;
  border-radius: 8px;
  padding: 24px;
  margin: 16px;
}

چک کن: حالا برچسبِ «جدید» پرید سرِ جای درستش — گوشهٔ بالا-راستِ همان کارتِ اول. چون کارت relative شد، مرورگر مختصاتِ top/rightِ برچسب را نسبت به کارت می‌سنجد، نه نسبت به صفحه. این الگو — یک والدِ relative و یک فرزندِ absolute — یکی از پرکاربردترین ترکیب‌های کلِ CSS است: هر وقت می‌خواهی چیزی را دقیقاً روی گوشه یا مرکزِ چیزِ دیگری بچسبانی، همین است.

⚠️ مواظب باش: اینجا right و left جهت‌های فیزیکی‌اند — right همیشه یعنی سمتِ راستِ صفحه، چه RTL چه LTR. در یک صفحهٔ فارسی که گوشهٔ «شروع» سمتِ راست است، right: -10px برچسب را به گوشهٔ ابتداییِ کارت می‌برد که طبیعی است. راهی هوشمندتر هم هست که خودش با جهتِ صفحه هماهنگ می‌شود؛ فعلاً با right/left جلو برو، فصل ۱۰ همین ترم کاملش می‌کنیم.

۴. fixed: همیشه گوشهٔ صفحه#

حالا یک دکمهٔ «کمک» می‌خواهیم که همیشه گوشهٔ صفحه بماند، حتی وقتی کاربر پایین اسکرول می‌کند. برای این position: fixed است. fixed هم مثل absolute عنصر را از جریان بیرون می‌کشد، ولی مختصاتش را همیشه نسبت به صفحهٔ نمایش (پنجرهٔ مرورگر) می‌سنجد، نه هیچ جدّی — پس هر چه اسکرول کنی، سرِ جایش میخ‌کوب می‌ماند.

اول در HTML، آخرِ body دکمه را اضافه کن:

<button class="float-btn">کمک</button>

و fixed اش کن، چسبیده به گوشهٔ پایین-چپ:

.float-btn {
  position: fixed;
  bottom: 20px;
  left: 20px;
  background-color: #55731b;
  color: #ffffff;
  border: none;
  padding: 12px 18px;
  border-radius: 999px;
  font-size: 1rem;
}

برای اینکه اثرش را ببینی به چند کارتِ دیگر نیاز داری تا صفحه بلند شود و اسکرول داشته باشد؛ دو سه <article class="card"> دیگر اضافه کن.

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

۵. sticky: تا یک‌جا عادی، بعد بچسب#

آخرین مقدار، باهوش‌ترینشان است: sticky. یک عنصرِ sticky تا وقتی که به لبهٔ تعیین‌شده نرسیده، مثل یک عنصرِ عادی در جریان حرکت می‌کند؛ ولی همین‌که اسکرول آن را به آن لبه رساند، همان‌جا می‌چسبد و دیگر پایین‌تر نمی‌رود. سرصفحهٔ فروشگاه را sticky کن تا موقعِ اسکرول بالای صفحه بماند:

.topbar {
  position: sticky;
  top: 0;
  background-color: #2a6b93;
  color: #ffffff;
  padding: 16px;
  font-size: 1.25rem;
}

آن top: 0 حیاتی است: به مرورگر می‌گوید «وقتی لبهٔ بالای نوار به فاصلهٔ صفرِ بالای صفحه رسید، همان‌جا بچسب». بدونش، sticky هیچ لبه‌ای برای چسبیدن ندارد و مثل عنصرِ عادی رفتار می‌کند.

چک کن: صفحه را آرام پایین اسکرول کن. اول نوارِ فروشگاه مثل بقیه بالا می‌رود؛ ولی همین‌که به بالای صفحه رسید، می‌چسبد و آنجا می‌ماند در حالی که کارت‌ها زیرش سُر می‌خورند. sticky ترکیبِ relative (تا قبل از لبه، عادی) و fixed (بعد از لبه، میخ‌کوب) است — و امروز رایج‌ترین راهِ ساختنِ سرصفحه‌ای است که همیشه در دسترس بماند.

🤖 با AI: از دستیار AI ات بپرس «فرقِ fixed و sticky در یک جمله چیست؟». جوابش را با چیزی که همین الان دیدی بسنج: هر دو را روی نوار امتحان کن و با چشمت ببین کدام از همان اول میخ‌کوب است و کدام اول عادی حرکت می‌کند بعد می‌چسبد. تا خودت اسکرول نکرده‌ای و ندیده‌ای، حرفِ 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>
    <header class="topbar">فروشگاه من</header>

    <main>
      <article class="card">
        <div class="badge">جدید</div>
        <h2>هدفون بی‌سیم</h2>
        <p>صدای شفاف و باتری طولانی.</p>
      </article>
      <article class="card">
        <h2>کیبورد مکانیکی</h2>
        <p>تایپ سریع و لمس دقیق.</p>
      </article>
      <article class="card">
        <h2>ماوس سبک</h2>
        <p>مناسب بازی و کار روزمره.</p>
      </article>
      <article class="card">
        <h2>وب‌کم HD</h2>
        <p>تصویر واضح برای جلسه‌ها.</p>
      </article>
    </main>

    <button class="float-btn">کمک</button>
  </body>
</html>

و styles.css:

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

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

.topbar {
  position: sticky;
  top: 0;
  background-color: #2a6b93;
  color: #ffffff;
  padding: 16px;
  font-size: 1.25rem;
}

main {
  padding: 16px;
}

.card {
  position: relative;
  background-color: #ffffff;
  border: 2px solid #2a6b93;
  border-radius: 8px;
  padding: 24px;
  margin-bottom: 16px;
}

.badge {
  position: absolute;
  top: -10px;
  right: -10px;
  background-color: #bc3e1c;
  color: #ffffff;
  padding: 4px 12px;
  border-radius: 999px;
}

.float-btn {
  position: fixed;
  bottom: 20px;
  left: 20px;
  background-color: #55731b;
  color: #ffffff;
  border: none;
  padding: 12px 18px;
  border-radius: 999px;
  font-size: 1rem;
}

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

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

کلمه تلفظ به حروف فارسی یعنی چه
position پوزیشِن تعیین می‌کند عنصر چطور جای‌گذاری شود
static استاتیک مقدارِ پیش‌فرض؛ جای عادی در جریانِ صفحه
relative ریلِتیو از جای عادی کمی جابه‌جا می‌شود ولی فضایش می‌ماند؛ لنگرِ فرزندِ absolute
absolute اَبسولوت از جریان بیرون می‌آید و نسبت به containing block جای‌گذاری می‌شود
fixed فیکسد نسبت به صفحهٔ نمایش میخ‌کوب می‌شود؛ با اسکرول تکان نمی‌خورد
sticky استیکی تا لبه عادی است، بعد می‌چسبد
containing block کانتینینگ بلاک جدّی که مختصاتِ عنصرِ absolute نسبت به آن سنجیده می‌شود

تمرین‌ها

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

در فصل بعد#

الان می‌توانی هر عنصری را از جریان بیرون بکشی و دقیقاً جای دلخواه بگذاری‌اش. ولی وقتی چند عنصرِ جای‌گذاری‌شده روی هم بیفتند، سؤالِ تازه‌ای پیش می‌آید: کدام رویِ کدام؟ فصل بعد سراغِ z-index و مفهومِ stacking context می‌رویم — و می‌بینی چرا گاهی یک z-index هرچقدر هم بزرگ باشد کار نمی‌کند. این یکی از چسبنده‌ترین سوءتفاهم‌های CSS است، پس با حوصله و مثال جلو می‌رویم.

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

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