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

فصل ۸ از ۱۱

پیشرفت ترم
۰٪

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

پس‌زمینه، حاشیه، سایه

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

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

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

یک کارت مطلب تمیز با یک نوار تصویری بالای آن، گوشه‌های گرد، یک حاشیهٔ نازک و یک سایهٔ ملایم که کارت را کمی از پس‌زمینه جدا می‌کند

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

  • به هر جعبه با border یک حاشیه و با border-radius گوشهٔ گرد بدهی
  • با box-shadow یک سایه بسازی که جعبه را از صفحه جدا کند
  • با background-image و background-size یک تصویر را درست داخل یک ناحیه جا بدهی
  • با linear-gradient() یک پس‌زمینهٔ رنگ‌به‌رنگ بسازی، بدون هیچ تصویری
  • بگویی چرا border-radius گاهی «انگار هیچ کاری نمی‌کند» و چطور درستش کنی

قبل از شروع#

  • از فصل ۴: box model و padding — تزئین روی همان جعبه‌ای می‌نشیند که آنجا شناختی.
  • از فصل ۵: رنگ با rgb() و opacity — سایه یک رنگِ نیمه‌شفاف است.
  • از فصل ۲: class — کارت را با یک class هدف می‌گیریم.

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

۱. یک کارت لخت برای شروع#

هر کارت اول یک تکهٔ HTML معمولی است. این را در آزمایشگاه داشته باش:

<article class="card">
  <div class="card-cover"></div>
  <p class="tag">آموزش</p>
  <h2>اولین روزم با CSS</h2>
  <p>امروز یاد گرفتم چطور یک جعبهٔ ساده را به یک کارت تمیز و خوش‌ظاهر تبدیل کنم.</p>
  <a class="more" href="#">ادامهٔ مطلب ←</a>
</article>

یک <article> (چون یک مطلبِ مستقل است، از فصل semantic یادت هست)، و تویش یک <div class="card-cover"> که فعلاً خالی است — این همان جایی است که بعداً تصویرِ کارت را می‌گذاریم. بقیه هم یک برچسب، یک تیتر، یک پاراگراف و یک لینک.

برای CSS هم فعلاً فقط جعبه را کمی جا می‌دهیم، عرضش را محدود می‌کنیم و وسطش می‌آوریم:

body {
  background-color: #eef1f7;
  padding: 40px;
}

.card {
  max-width: 320px;
  margin: 0 auto;
  padding: 16px;
}

اینجا دو property تازه داریم. max-width: 320px می‌گوید عرضِ کارت حداکثر ۳۲۰ پیکسل شود — جعبه از این پهن‌تر نمی‌شود ولی می‌تواند باریک‌تر بماند. و margin: 0 auto کارت را افقی وسط می‌آورد: وقتی یک جعبهٔ عرض‌محدود، margin چپ و راستش auto باشد، مرورگر فضای اضافه را دو طرفش مساوی پخش می‌کند و جعبه وسط می‌ایستد (آن 0 یعنی بالا و پایین بدونِ فاصله). padding را هم که از فصل ۴ بلدی.

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

۲. اول گوشه‌ها را گرد کن — و اولین غافلگیری#

اولین چیزی که یک کارت را «نرم» می‌کند، گوشه‌های گرد است. property اش border-radius است: هرچه عددش بزرگ‌تر، گوشه گردتر. به .card اضافه‌اش کن:

.card {
  max-width: 320px;
  margin: 0 auto;
  padding: 16px;
  border-radius: 16px;
}

حالا نگاه کن. و… هیچ اتفاقی نیفتاد. کارت دقیقاً همان‌شکلِ قبل است، انگار border-radius را اصلاً ننوشته‌ای. این یک خطای خیلی رایج است و ارزش دارد بفهمی چرا.

🔧 اگر کار نکرد: border-radius گوشهٔ لبهٔ دیدنیِ جعبه را گرد می‌کند — یعنی جایی که یک رنگِ پس‌زمینه یا یک حاشیه تمام می‌شود. کارتِ ما هنوز نه پس‌زمینه دارد نه حاشیه؛ پس هیچ لبهٔ دیدنی‌ای نیست که گرد شود. گوشه‌ها واقعاً گرد شده‌اند، ولی چون چیزی آنجا کشیده نشده، دیدنی نیست. راهِ حل ساده است: در قدم بعد به کارت یک پس‌زمینه و یک حاشیه می‌دهیم و همان لحظه گوشه‌های گرد ظاهر می‌شوند.

۳. حاشیه و پس‌زمینه: حالا لبه دیده می‌شود#

دو چیز به .card اضافه می‌کنیم. اول یک background-color که کارت را از صفحه جدا کند، و بعد یک border.

border یک property جمع‌وجور است که سه چیز را با هم می‌گیرد: کلفتی، نوع خط و رنگ — به همین ترتیب. مثلاً 1px solid #e4e8f0 یعنی «یک خطِ توپُرِ یک‌پیکسلیِ خاکستری روشن».

.card {
  max-width: 320px;
  margin: 0 auto;
  padding: 16px;
  background-color: #ffffff;
  border: 1px solid #e4e8f0;
  border-radius: 16px;
}

چک کن: حالا یک کارتِ سفید با یک حاشیهٔ نازکِ خاکستری روی پس‌زمینهٔ کم‌رنگ می‌بینی — و گوشه‌هایش گرد است. همان border-radius قدمِ قبل، حالا که یک لبهٔ دیدنی (رنگِ سفید + حاشیه) دارد، خودش را نشان می‌دهد. حالا خرابش کن تا حس کنی: border-radius را به 0 عوض کن و ببین گوشه‌ها تیز می‌شوند، بعد 40px بگذار و ببین چقدر گرد می‌شود. عدد را حس کن، بعد برگردان روی 16px.

💡 نکته: solid تنها نوع خط نیست. dashed (خط‌چین) و dotted (نقطه‌چین) هم هستند. برای کارت solid بهترین است، ولی خوب است بدانی گزینه‌ها هستند.

قبل از ادامه، جواب بده: اگر border را کلاً پاک کنی ولی background-color سفید بماند، باز هم گوشه‌ها گرد دیده می‌شوند؟

بله. چون حالا یک لبهٔ دیدنی داری: جایی که سفیدِ کارت تمام می‌شود و خاکستریِ صفحه شروع. border-radius همان مرزِ رنگ را گرد می‌کند، چه حاشیه باشد چه نباشد. لبهٔ دیدنی است که مهم است، نه لزوماً حاشیه.

۴. سایه: کارت را از صفحه بلند کن#

چیزی که کارت را واقعاً «کارت» می‌کند، یک سایهٔ ملایم است که انگار کارت را کمی از صفحه بلند کرده. property اش box-shadow است و چهار مقدار پشت‌سرِ هم می‌گیرد:

box-shadow: 0 12px 30px rgb(23 36 64 / 0.14);

این چهار تکه به‌ترتیب یعنی:

  • 0 — جابه‌جایی افقی سایه (اینجا صفر: سایه به چپ و راست نمی‌رود).
  • 12px — جابه‌جایی عمودی: سایه ۱۲ پیکسل پایین‌تر می‌افتد، انگار نور از بالا می‌تابد.
  • 30px — میزان محو‌شدگیِ سایه: هرچه بزرگ‌تر، سایه نرم‌تر و پخش‌تر.
  • rgb(23 36 64 / 0.14) — رنگِ سایه. این یک شکلِ تازهٔ نوشتنِ رنگ است: بعد از سه عددِ rgb یک / می‌گذاری و بعدش یک عددِ شفافیت — یعنی rgb(r g b / alpha). همان ایدهٔ شفافیتی که در فصل ۵ با opacity دیدی، این‌بار مستقیم داخلِ خودِ رنگ نوشته می‌شود، پس فقط همین رنگ نیمه‌شفاف می‌شود نه کلِ عنصر. سایهٔ خوب هیچ‌وقت مشکیِ توپُر نیست؛ یک آبیِ خیلی کم‌رنگ و کم‌شفاف طبیعی‌تر است.

به .card اضافه‌اش کن:

.card {
  max-width: 320px;
  margin: 0 auto;
  padding: 16px;
  background-color: #ffffff;
  border: 1px solid #e4e8f0;
  border-radius: 16px;
  box-shadow: 0 12px 30px rgb(23 36 64 / 0.14);
}

چک کن: حالا کارت انگار کمی از صفحه بلند شده و یک سایهٔ نرم زیرش افتاده. حالا خرابش کن: مقدار محو‌شدگی را از 30px به 2px عوض کن و ببین سایه چقدر تیز و بدقواره می‌شود؛ بعد جابه‌جاییِ عمودی را 40px بگذار و ببین کارت انگار خیلی بالا شناور شده. با همین دو عدد بازی کن تا حسِ سایه در دستت بیاید، بعد برگردان روی 0 12px 30px.

💡 نکته: رازِ سایهٔ حرفه‌ای این است: جابه‌جایی کم، محو‌شدگیِ زیاد، رنگِ کم‌شفاف. سایهٔ تیره و تیز، کارت را ارزان نشان می‌دهد؛ سایهٔ نرم و کم‌رنگ، گران.

۵. gradient: پس‌زمینهٔ رنگ‌به‌رنگ بدون تصویر#

تا حالا پس‌زمینه‌ها یک‌رنگ بودند. linear-gradient() می‌گذارد رنگ به‌آرامی از یکی به دیگری برود — بدون هیچ فایلِ تصویری، فقط با CSS. یک نکتهٔ مهم: gradient در CSS یک تصویر حساب می‌شود، نه یک رنگ. برای همین توی background-image می‌نشیند، نه background-color.

بیا پس‌زمینهٔ کلِ صفحه را از خاکستریِ تخت به یک gradient نرم عوض کنیم. در body:

body {
  background-image: linear-gradient(160deg, #eef1f7, #d9e0ee);
  padding: 40px;
}

داخل پرانتز، اول جهت را می‌گویی (160deg یعنی یک زاویهٔ مورب) و بعد رنگ‌ها را به‌ترتیب. مرورگر خودش بینشان را نرم پُر می‌کند.

چک کن: پس‌زمینهٔ صفحه دیگر تخت نیست؛ از یک گوشه به گوشهٔ دیگر کمی رنگش عوض می‌شود. حالا خرابش کن: 160deg را 90deg کن و ببین جهتِ گذارِ رنگ عوض می‌شود؛ یک رنگِ سوم هم اضافه کن — linear-gradient(160deg, #eef1f7, #d9e0ee, #c7d0e6) — و ببین سه‌تایی می‌شود.

⚠️ مواظب باش: یک اشتباهِ خیلی رایج این است که gradient را داخلِ background-color بنویسی. کار نمی‌کند و هیچ خطایی هم نمی‌بینی — چون gradient یک تصویر است، نه یک رنگ. همیشه توی background-image بگذارش.

۶. تصویرِ واقعی در پس‌زمینه، و background-size#

حالا سراغِ آن <div class="card-cover"> می‌رویم که از قدمِ اول خالی گذاشتیمش. می‌خواهیم یک تصویر تویش بنشیند. با background-image: url(...) یک تصویر را پس‌زمینهٔ یک ناحیه می‌کنی. ولی یک مشکل هست: تصویر معمولاً هم‌اندازهٔ آن ناحیه نیست. اینجا background-size وارد می‌شود:

  • cover — تصویر را آن‌قدر بزرگ می‌کند که کلِ ناحیه را بپوشاند، حتی اگر لبه‌هایش کمی بیرون بزند. برای عکسِ کاور همین را می‌خواهی.
  • contain — تصویر را آن‌قدر کوچک می‌کند که کامل داخل ناحیه جا شود، حتی اگر گوشه‌ها خالی بماند.

به .card-cover این‌ها را بده:

.card-cover {
  height: 150px;
  border-radius: 12px;
  background-image: url("https://picsum.photos/seed/taropood/400/220");
  background-size: cover;
  background-position: center;
}

height به ناحیه یک بلندی می‌دهد (وگرنه چون خالی است، ارتفاعش صفر می‌شود و تصویر دیده نمی‌شود). background-position: center هم می‌گوید وسطِ تصویر را نشانم بده. و border-radius: 12px گوشه‌های همین نوارِ تصویری را هم گرد می‌کند تا با کارت هماهنگ باشد.

چک کن: بالای کارت یک نوارِ تصویریِ گوشه‌گرد ظاهر شد که کلِ عرض را پُر کرده. حالا خرابش کن: background-size را از cover به contain عوض کن و ببین تصویر کوچک می‌شود و دوطرفش خالی می‌ماند؛ بعد کلاً پاکش کن و ببین تصویر با اندازهٔ اصلیِ خودش می‌افتد و بدقواره می‌شود. حالا فهمیدی background-size دقیقاً چه کاری می‌کند. برگردان روی cover.

🤖 با AI: یک box-shadow سه‌مقداری به دستیار AI ات بده — مثلاً box-shadow: 0 12px 30px rgb(23 36 64 / 0.14) — و بپرس «هر عدد اینجا چه‌کار می‌کند؟». بعد همان اعداد را در آزمایشگاه یکی‌یکی عوض کن و جوابش را با چیزی که می‌بینی چک کن. اگر AI گفت عددِ دوم «محوشدگی» است، خودت با تغییرش ثابت کن که نه — عددِ سوم محوشدگی است. این‌طوری هم یاد می‌گیری، هم عادت می‌کنی حرفِ AI را با چشمِ خودت بسنجی.

۷. کارتِ کامل#

حالا همه‌چیز را کنار هم می‌گذاریم. این HTML و CSSِ نهاییِ کارت است. اول 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>
    <article class="card">
      <div class="card-cover"></div>
      <p class="tag">آموزش</p>
      <h2>اولین روزم با CSS</h2>
      <p>امروز یاد گرفتم چطور یک جعبهٔ ساده را به یک کارت تمیز و خوش‌ظاهر تبدیل کنم.</p>
      <a class="more" href="#">ادامهٔ مطلب ←</a>
    </article>
  </body>
</html>

و CSSِ کامل — همان تکه‌ها که ساختیم، به‌علاوهٔ چند خطِ ساده برای رنگ و فاصلهٔ متن‌ها (چیزهایی که از فصل‌های رنگ و تایپوگرافی بلدی):

/* styles.css */
body {
  font-family: Tahoma, sans-serif;
  background-image: linear-gradient(160deg, #eef1f7, #d9e0ee);
  padding: 40px;
}

.card {
  max-width: 320px;
  margin: 0 auto;
  padding: 16px;
  background-color: #ffffff;
  border: 1px solid #e4e8f0;
  border-radius: 16px;
  box-shadow: 0 12px 30px rgb(23 36 64 / 0.14);
}

.card-cover {
  height: 150px;
  border-radius: 12px;
  background-image: url("https://picsum.photos/seed/taropood/400/220");
  background-size: cover;
  background-position: center;
}

.tag {
  margin-top: 14px;
  margin-bottom: 4px;
  color: #5a4bff;
  font-weight: 700;
}

.card h2 {
  margin: 0 0 8px;
  color: #172440;
}

.card p {
  margin: 0;
  color: #55607a;
  line-height: 1.9;
}

.more {
  display: inline-block;
  margin-top: 12px;
  color: #5a4bff;
  font-weight: 700;
}

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

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

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

کلمه تلفظ به حروف فارسی یعنی چه
border بوردِر حاشیهٔ دور جعبه؛ کلفتی + نوع خط + رنگ
border-radius بوردِر رِیدیوس گرد کردن گوشه‌های لبهٔ دیدنیِ جعبه
box-shadow باکس شَدو سایهٔ جعبه؛ جابه‌جایی افقی، عمودی، محوشدگی، رنگ
background-image بک‌گراند ایمیج تصویر (یا gradient) به‌عنوان پس‌زمینهٔ یک ناحیه
background-size بک‌گراند سایز چطور تصویرِ پس‌زمینه در ناحیه جا شود (cover / contain)
gradient گِرِیدینت گذارِ نرمِ رنگ؛ در CSS یک تصویر است، نه یک رنگ

تمرین‌ها

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

در فصل بعد#

الان می‌توانی به جعبه‌ها ظاهرِ حرفه‌ای بدهی — ولی احتمالاً همین حالا یک رنگ را در چند جای CSS ات تکرار کرده‌ای (مثلاً همان #5a4bff که هم برای برچسب هم برای لینک نوشتیم). اگر بخواهی این رنگِ اصلیِ سایت را عوض کنی، باید دنبال تک‌تکشان بگردی. فصل بعد یاد می‌گیری رنگ‌ها و اندازه‌های تکراری را یک‌بار با یک اسمِ خودت تعریف کنی و همه‌جا صدایشان بزنی — به این می‌گویند custom property، و پایهٔ ساختنِ theme (و بعدها dark mode) همین است.

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

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