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

فصل ۱۰ از ۱۱

پیشرفت ترم
۰٪

ترم ۶ · حرفه‌ای و واقعی

پروژهٔ نهایی: ساخت سایت چندصفحه‌ای

فصل ۱۰پیش‌نمایش رایگان

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

رسیدی به پروژهٔ نهایی. مفهومِ تازه‌ای در کار نیست — کارِ امروز ترکیب است: هر چیزی که در پنج ترمِ گذشته یاد گرفتی را در یک سایتِ واقعی کنارِ هم می‌گذاری. یک نمونه‌کارِ کوچک (portfolio) با دو صفحه: یک صفحهٔ خانه که کارهایت را در یک گریدِ کارت نشان می‌دهد، و یک صفحهٔ جزئیات برای یک کار — و هر دو یک سرصفحه و پاصفحهٔ مشترک دارند. توی این یک پروژه، semantic HTML، layout، responsive، dark mode، component و token همه با هم جمع‌اند.

طرحِ یک سایتِ نمونه‌کار: بالا یک سرصفحهٔ مشترک با نامِ سازنده یک‌سو و منو سویِ دیگر، وسط یک ردیف کارتِ هم‌اندازه روی یک گرید، و پایین یک پاصفحهٔ مشترک؛ کنارش همان صفحه در حالتِ تیره

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

  • یک سرصفحه و پاصفحهٔ مشترک بسازی که در چند صفحه یکسان بماند
  • کارها را در یک گریدِ responsive بچینی که خودش تعدادِ ستون را با پهنای صفحه جور می‌کند
  • theme روشن و تیره را با token به کلِ سایت بدهی
  • چند صفحه را با پیوندهای واقعی به هم وصل کنی

قبل از شروع#

  • از ترم ۱: ساختارِ semantic — <header>، <nav>، <main>، <section>، <article>، <footer>.
  • از ترم ۳: flexbox برای سرصفحه و grid با repeat(auto-fit, minmax(...)) برای کارت‌ها.
  • از ترم ۴: clamp() برای فونتِ سیال و prefers-color-scheme برای dark mode.
  • از ترم ۶: فکرِ component و token، و اگر گیر کردی، اشکال‌زداییِ فصل قبل.

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

۱. نقشهٔ سایت#

اول نقشه، بعد کد. سایت دو صفحه دارد:

  • index.html — صفحهٔ خانه: یک معرفیِ کوتاه و یک گرید از کارتِ کارها.
  • project.html — صفحهٔ جزئیاتِ یک کار: عنوان، یک تصویر و چند پاراگراف.

هر دو صفحه همان <header> و <footer> و همان styles.css را دارند. این نکتهٔ اصلیِ یک سایتِ چندصفحه‌ای است: یک stylesheet مشترک، پس theme و سرصفحه فقط یک‌بار نوشته می‌شوند و همه‌جا یکسان‌اند.

۲. پایه: token و تمِ روشن/تیره#

از فصلِ dark mode یادت هست: رنگ‌ها را یک‌جا روی :root به‌عنوان token تعریف می‌کنی، و در @media (prefers-color-scheme: dark) مقدارشان را عوض می‌کنی. همین پایه را می‌گذاریم:

:root {
  color-scheme: light dark;
  --bg: #f6edda;
  --card: #ffffff;
  --ink: #2c2114;
  --muted: #6b6150;
  --brand: #2a6b93;
  --line: #d8ccae;
  --space: 20px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14181f;
    --card: #1e2530;
    --ink: #f2f4f8;
    --muted: #aab3c5;
    --line: #2c3644;
  }
}

بقیهٔ CSS به‌جای رنگِ ثابت، var(--bg)، var(--ink) و مثلِ این‌ها را صدا می‌زند — پس کلِ سایت با تمِ سیستم، روشن و تیره می‌شود بی‌آنکه یک رنگ را دوباره بنویسی.

۳. سرصفحه و پاصفحهٔ مشترک#

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

.site-header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space);
  padding: 14px var(--space);
  background-color: var(--card);
  border-block-end: 1px solid var(--line);
}

.site-footer {
  padding-block: 20px;
  text-align: center;
  color: var(--muted);
  border-block-start: 1px solid var(--line);
}

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

۴. صفحهٔ خانه: گریدِ کارت‌ها#

حالا مهم‌ترین بخش: کارها باید در چند کارتِ هم‌اندازه کنارِ هم بنشینند. اولین فکر شاید این باشد که سه ستونِ ثابت بدهی:

.grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--space);
}

روی صفحهٔ پهن قشنگ است. حالا پنجره را باریک کن — مثلِ صفحهٔ موبایل. سه کارت سرِ جاشان می‌مانند ولی هر کدام آن‌قدر باریک می‌شوند که متن‌ها له می‌شوند و کارت‌ها زشت و بلند می‌شوند. سه ستون همیشه سه ستون است، حتی وقتی جا نیست.

🔧 اگر کار نکرد: به‌جای عددِ ثابتِ ستون‌ها، از مرورگر بخواه خودش تصمیم بگیرد. repeat(auto-fit, minmax(220px, 1fr)) یعنی «هر کارت حداقل ۲۲۰ پیکسل باشد، و هرچند تا که در این عرض جا می‌شود کنارِ هم بچین؛ باقی را ببر خطِ بعد». روی صفحهٔ پهن سه‌تایی می‌شوند، روی صفحهٔ باریک خودشان می‌روند زیرِ هم و بزرگ و خوانا می‌مانند — بدونِ حتی یک @media. این همان auto-fitِ ترم ۳ است، و اینجا نشان می‌دهد چرا آن روز یادش گرفتی.

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space);
  margin: 0;
  padding: 0;
}

چک کن: پنجره را پهن و باریک کن. کارت‌ها خودشان از سه ستون به دو و به یک ستون می‌روند و هیچ‌وقت له نمی‌شوند. این یعنی responsive.

دو حالتِ یک ردیف کارت کنارِ هم: سمتی سه ستونِ ثابت که در صفحهٔ باریک به سه نوارِ باریک و لهیده تبدیل شده‌اند، سمتِ دیگر همان کارت‌ها که در صفحهٔ باریک زیرِ هم و بزرگ و خوانا چیده شده‌اند

۵. صفحهٔ دوم و پیوند بینشان#

صفحهٔ خانه آماده است. صفحهٔ دوم، project.html، دقیقاً همان <header> و <footer> و همان <link rel="stylesheet" href="styles.css"> را دارد؛ فقط <main> اش فرق می‌کند: یک <article> با یک <h1> عنوانِ کار، یک تصویر با max-width: 100% (تا هیچ‌وقت از صفحه بیرون نزند — همان درسِ فصل قبل)، و چند پاراگراف توضیح. چون stylesheet مشترک است، این صفحه بدونِ یک خطِ CSS تازه، همان ظاهر و همان تمِ روشن/تیره را می‌گیرد.

پیوندِ بینشان با همان <a href>ِ ترم ۱ ساخته می‌شود: در کارت‌های خانه href="project.html" می‌گذاری، و در صفحهٔ جزئیات یک لینکِ بازگشت با href="index.html". همین دو مسیرِ نسبی، دو صفحه را به یک سایت تبدیل می‌کند.

۶. کدِ کامل#

اول index.html:

<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>پروانه پارسا — نمونه‌کارها</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <header class="site-header">
      <a class="logo" href="index.html">پروانه پارسا</a>
      <nav>
        <ul class="menu">
          <li><a href="index.html">خانه</a></li>
          <li><a href="#works">نمونه‌کارها</a></li>
          <li><a href="#about">درباره</a></li>
        </ul>
      </nav>
    </header>

    <main>
      <section class="intro">
        <h1>سلام، من پروانه‌ام</h1>
        <p>سازندهٔ صفحه‌های وب. اینجا چند کاری که ساخته‌ام را می‌بینی.</p>
      </section>

      <section id="works" class="works">
        <h2>نمونه‌کارها</h2>
        <ul class="grid">
          <li class="card">
            <article>
              <h3><a href="project.html">فروشگاه گل</a></h3>
              <p>یک صفحهٔ فروشگاهیِ ساده با گرید و کارتِ محصول.</p>
            </article>
          </li>
          <li class="card">
            <article>
              <h3><a href="project.html">تقویم رویداد</a></h3>
              <p>فهرستِ رویدادها با تایپوگرافیِ تمیز و حالتِ تیره.</p>
            </article>
          </li>
          <li class="card">
            <article>
              <h3><a href="project.html">صفحهٔ سفر</a></h3>
              <p>یک صفحهٔ معرفیِ شهر با تصویرِ responsive.</p>
            </article>
          </li>
        </ul>
      </section>

      <section id="about" class="about">
        <h2>درباره</h2>
        <p>تازه دنیای وب را تمام کرده‌ام و با HTML و CSS صفحه می‌سازم. این سایت خودش یکی از کارهاست.</p>
      </section>
    </main>

    <footer class="site-footer">
      <p>ساختهٔ پروانه پارسا — ۱۴۰۵</p>
    </footer>
  </body>
</html>

و styles.css، از اول تا آخر:

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

/* ---------- tokens (roshan) ---------- */
:root {
  color-scheme: light dark;
  --bg: #f6edda;
  --card: #ffffff;
  --ink: #2c2114;
  --muted: #6b6150;
  --brand: #2a6b93;
  --line: #d8ccae;
  --space: 20px;
}

/* ---------- tokens (tire) ---------- */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14181f;
    --card: #1e2530;
    --ink: #f2f4f8;
    --muted: #aab3c5;
    --line: #2c3644;
  }
}

/* ---------- base ---------- */
body {
  margin: 0;
  font-family: Tahoma, sans-serif;
  color: var(--ink);
  background-color: var(--bg);
  line-height: 1.9;
}

/* ---------- header + footer (moshtarak) ---------- */
.site-header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space);
  padding: 14px var(--space);
  background-color: var(--card);
  border-block-end: 1px solid var(--line);
}

.logo {
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--brand);
}

.menu {
  display: flex;
  gap: 16px;
  margin: 0;
  padding: 0;
}

.menu a {
  color: var(--ink);
  font-weight: 700;
}

.site-footer {
  padding-block: 20px;
  text-align: center;
  color: var(--muted);
  border-block-start: 1px solid var(--line);
}

/* ---------- main ---------- */
main {
  max-width: 900px;
  margin-inline: auto;
  padding: var(--space);
}

.intro h1 {
  margin-block: 0 8px;
  font-size: clamp(1.6rem, 5vw, 2.4rem);
}

.about {
  margin-block-start: var(--space);
}

/* ---------- works grid + card ---------- */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space);
  margin: 0;
  padding: 0;
}

.card {
  padding: var(--space);
  background-color: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
}

.card h3 {
  margin-block: 0 8px;
}

.card a {
  color: var(--brand);
}

.card p {
  margin: 0;
  color: var(--muted);
}

چک کن: صفحهٔ کامل را نگاه کن — سرصفحهٔ flex، گریدِ کارت‌های responsive، و در تمِ تیرهٔ سیستم، کلِ سایت تیره و خوانا. نقطه‌های فهرست هم رفتند، چون <ul> را grid و flex کردیم و آیتم‌هایش دیگر «آیتمِ فهرست» حساب نمی‌شوند. این یک سایتِ واقعی است، ساخته از هرچه بلدی.

🤖 با AI: کلِ صفحه‌ات را به دستیار AI ات بده و بپرس «آیا ساختارِ semantic و ترتیبِ heading این صفحه درست است؟». این یکی از بهترین کاربردهای AI است — یک بازبینیِ دسترس‌پذیری، بعد از اینکه خودت نوشتی. ولی هر پیشنهادش را در DevTools و با فهمِ خودت بسنج؛ گاهی یک <div> یا roleِ بی‌لزوم اضافه می‌کند که تو با درسِ ترم ۱ می‌دانی لازم نیست.

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

این فصلِ پروژه‌ای است و واژهٔ فنیِ تازه‌ای ندارد؛ فقط ابزارهای پنج ترم — semantic HTML، flexbox، grid، auto-fit، clamp()، prefers-color-scheme و token — را در یک سایت کنارِ هم می‌گذارد.

تمرین‌ها

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

در فصل بعد#

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

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

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