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

فصل ۶ از ۱۱

پیشرفت ترم
۰٪

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

تایپوگرافی و فونت فارسی

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

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

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

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

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

  • با font-family فونتِ متن را عوض کنی و یک stack ‌ی fallback بنویسی
  • با @font-face یک فونتِ فارسیِ واقعی را بار کنی و به‌کار ببری
  • با font-size و line-height به متنِ فارسی جای نفس بدهی
  • با font-weight و text-align عنوان و متن را مرتب کنی

قبل از شروع#

  • از فصل ۵: واحد rem — اندازهٔ فونت‌ها را با آن می‌نویسیم، و color.
  • از فصل ۴: padding و عادتِ box-sizing: border-box.
  • از فصل ۱: <link rel="stylesheet">.

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

۱. font-family: انتخابِ فونت#

با font-family می‌گویی متن با چه فونتی نوشته شود. ولی یک نکتهٔ مهم دارد: تو نمی‌دانی کاربر چه فونت‌هایی روی دستگاهش دارد. برای همین معمولاً یک stack می‌نویسی — یعنی یک فهرست از فونت‌ها به‌ترتیبِ اولویت. مرورگر از اولی شروع می‌کند؛ اگر نبود می‌رود سراغ بعدی، تا به یکی برسد که هست.

اول ساختارِ مطلب را در HTML بنویس — یک مطلب با یک عنوان، یک خطِ اول که کمی برجسته‌تر است (lead)، و دو پاراگراف:

<!-- 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="post">
      <h1>چرا فونت مهم است</h1>
      <p class="lead">یک متن با فونتِ خوب خوانده می‌شود؛ با فونتِ بد فقط دیده می‌شود.</p>
      <p>حروفِ فارسی به هم می‌چسبند و با هم شکل می‌گیرند، برای همین به فونتی نیاز دارند که این پیوندها را درست بکشد. فونتِ پیش‌فرضِ خیلی از مرورگرها این کار را خوب انجام نمی‌دهد.</p>
      <p>با یک فونتِ وبِ مناسب و کمی فاصلهٔ بیشتر بین خط‌ها، همین متن راحت‌تر خوانده می‌شود و چشم زودتر خسته نمی‌شود.</p>
    </article>
  </body>
</html>

حالا در آزمایشگاه، این مطلب را با یک stack ساده امتحان کن:

body {
  font-family: Tahoma, sans-serif;
}

آخرین عضوِ stack همیشه یک نامِ عمومی است: sans-serif (بدونِ سرِ‌کج، ساده) یا serif (با سرِ‌کج، رسمی‌تر). این تضمین می‌کند حتی اگر هیچ‌کدام از فونت‌های قبلی نبودند، مرورگر دستِ‌کم یک فونتِ هم‌خانواده می‌گذارد.

چک کن: برای اینکه ببینی font-family واقعاً کار می‌کند، آخرین کلمه را به serif عوض کن (font-family: Tahoma, serif; نه، کلاً font-family: serif;) و بعد sans-serif. تفاوتِ حروف را می‌بینی — یکی سرِ حروف را ساده می‌کشد، دیگری با زائده. پس فونت عوض می‌شود. ولی هیچ‌کدامِ این‌ها فونتِ دلخواهِ ما نیستند؛ فقط چیزی‌اند که روی دستگاه هست. برای فونتِ دلخواه، باید خودمان بارش کنیم.

۲. font-face: بار کردن یک فونتِ فارسی#

@font-face به مرورگر می‌گوید «یک فونت از این آدرس بردار و به این اسم صدایش کن». بعد می‌توانی آن اسم را در font-family به‌کار ببری. یک فونتِ فارسیِ آزاد و بسیار خوانا به اسم Vazirmatn را بار می‌کنیم. این دو بلوک را بالای فایل CSS بگذار:

@font-face {
  font-family: "Vazirmatn";
  src: url("https://cdn.jsdelivr.net/npm/@fontsource/vazirmatn/files/vazirmatn-arabic-400-normal.woff2") format("woff2");
  font-weight: 400;
}

@font-face {
  font-family: "Vazirmatn";
  src: url("https://cdn.jsdelivr.net/npm/@fontsource/vazirmatn/files/vazirmatn-arabic-700-normal.woff2") format("woff2");
  font-weight: 700;
}

هر بلوک سه چیز می‌گوید: اسمی که با آن صدایش می‌زنیم (font-family: "Vazirmatn")، آدرسِ فایلِ فونت (src)، و اینکه این فایل کدام وزن است (font-weight — یکی نازک ۴۰۰، یکی پُر ۷۰۰). دو بلوک، یک اسم: مرورگر خودش می‌فهمد برای متنِ عادی کدام و برای متنِ پُر کدام را بردارد.

حالا این فونت را به کلِ صفحه بده. به‌جای Tahoma، Vazirmatn را اولِ stack می‌گذاریم — ولی حواست باشد، اینجا عمداً یک اشتباهِ کوچک می‌کنیم تا چیزی یاد بگیری:

body {
  font-family: Vazir, Tahoma, sans-serif;
}

به صفحه نگاه کن. فونت عوض نشد — هنوز همان Tahoma است. عجیب است: فونت را بار کردیم، اسمش را هم در font-family نوشتیم، پس چرا نگرفت؟

🔧 اگر کار نکرد: این عمدی است و یکی از رایج‌ترین دام‌هاست. دقیق نگاه کن: در @font-face اسم را "Vazirmatn" گذاشتیم، ولی در font-family نوشتیم Vazir. این دو یکی نیستند. مرورگر دنبال فونتی به‌نامِ Vazir می‌گردد، همچین چیزی بار نشده، پس بی‌سروصدا می‌پرد سراغ عضوِ بعدیِ stack یعنی Tahoma. هیچ پیامِ خطایی هم نمی‌دهد — فقط فونتِ دلخواهت را نادیده می‌گیرد. اسمی که در @font-face تعریف می‌کنی و اسمی که در font-family صدا می‌زنی باید مو‌به‌مو یکی باشند.

درستش کن — Vazir را به Vazirmatn تبدیل کن:

body {
  font-family: "Vazirmatn", Tahoma, sans-serif;
}

چک کن: حالا متن با Vazirmatn نمایش داده می‌شود — حروفِ فارسی تمیزتر و یک‌دست‌ترند. برای مطمئن‌شدن، اسم را دوباره خراب کن (مثلاً "Vazirmatnn") و ببین فونت فوراً به Tahoma برمی‌گردد؛ بعد درستش کن. این رفت‌وبرگشت، درسِ اسم‌ها را برای همیشه جا می‌اندازد.

💡 نکته: در پروژهٔ واقعیِ خودت معمولاً فایلِ فونت را کنارِ CSS می‌گذاری و src را کوتاه می‌نویسی، مثل url("vazirmatn.woff2"). اینجا در آزمایشگاه به یک نسخهٔ آنلاین آدرس داده‌ایم تا همین حالا و بدونِ دانلود ببینی‌اش. هر دو یک کار می‌کنند؛ فقط آدرس فرق دارد.

۳. font-size و line-height: جای نفس#

حالا که فونت درست است، سراغِ خوانایی می‌رویم. دو ابزار مهم داریم. font-size اندازهٔ متن است — که از فصل ۵ می‌دانیم بهتر است با rem نوشته شود. line-height فاصلهٔ بین خط‌هاست — و برای فارسی خیلی مهم است، چون حروفِ فارسی زیر و بالا دنباله دارند و خط‌های چسبیده به‌هم، متن را خفه می‌کنند.

به مطلب کمی اندازه و فاصله بده:

.post {
  font-size: 1.125rem;
  line-height: 1.9;
  padding: 24px;
}

line-height: 1.9 یعنی هر خط ۱٫۹ برابرِ اندازهٔ فونت جا می‌گیرد — یک عددِ بی‌واحد که به اندازهٔ فونتِ همان عنصر گره می‌خورد، پس اگر فونت بزرگ شود فاصله هم خودش بزرگ می‌شود.

چک کن: متن حالا بازتر و خواناتر است. عدد line-height را به 1.2 کم کن و ببین چطور خط‌ها به‌هم می‌چسبند و خواندن سخت می‌شود؛ بعد به 1.9 برگردان و راحتی را حس کن. برای متنِ فارسی، جایی بین 1.7 تا 2 معمولاً خوب است.

💡 نکته: چرا فارسی به فاصلهٔ بیشتری از خط‌های لاتین نیاز دارد؟ چون حروفِ فارسی نقطه و دنباله‌های بالا و پایین دارند (به «ژ»، «چ»، «گ» نگاه کن) و اگر خط‌ها فشرده باشند، این دنباله‌ها به خطِ بالا و پایین نزدیک می‌شوند و متن شلوغ به‌نظر می‌رسد. کمی line-heightِ بیشتر به این دنباله‌ها جا می‌دهد و همین، تفاوتِ یک صفحهٔ فارسیِ خوانا و یک صفحهٔ خسته‌کننده است.

قبل از ادامه، جواب بده: چرا برای line-height یک عددِ بی‌واحد (مثل 1.9) بهتر از یک مقدارِ ثابت (مثل 30px) است؟ (چون بی‌واحد با هر اندازهٔ فونتی خودش را تنظیم می‌کند؛ مقدارِ ثابت اگر فونت بزرگ شود خفه‌کننده می‌شود.)

۴. font-weight: درشتیِ متن#

font-weight می‌گوید متن چقدر پُر و کلفت باشد. رایج‌ترین‌ها 400 (عادی) و 700 (پُر، همان bold) هستند — و یادت هست که در @font-face برای هرکدام یک فایل بار کردیم، پس مرورگر واقعاً فایلِ درست را می‌گذارد، نه یک کلفتیِ ساختگی. عنوان و خطِ اولِ مطلب را پُر کن:

.post h1 {
  font-weight: 700;
}

.lead {
  font-weight: 700;
}

چک کن: عنوان و خطِ اولِ مطلب حالا درشت و پُرند و از بقیهٔ متن جدا می‌شوند. مقدارِ 700 را به 400 عوض کن و ببین چطور به وزنِ عادی برمی‌گردند.

💡 نکته: font-weight عددهای دیگری هم می‌پذیرد، از 100 (خیلی نازک) تا 900 (خیلی سنگین)، پله‌پله صدتا‌صدتا. ولی یک فونت فقط وزن‌هایی را واقعاً نشان می‌دهد که برایشان فایل بار کرده باشی؛ ما در @font-face دو فایل بار کردیم (400 و 700)، پس همین دو وزن دقیق‌اند و بقیهٔ عددها به نزدیک‌ترین فایلِ موجود گرد می‌شوند.

۵. text-align: چینشِ متن#

text-align می‌گوید متن به کدام سمت بچسبد. چون صفحهٔ ما فارسی و dir="rtl" است، متن به‌طور پیش‌فرض از راست می‌چیند — همان چیزی که برای پاراگراف‌های فارسی درست است. ولی عنوان را وسط‌چین می‌کنیم تا شاخص شود:

.post h1 {
  font-weight: 700;
  text-align: center;
}

چک کن: عنوان حالا وسطِ صفحه است. مقدار را به left عوض کن تا به چپ برود، بعد right، بعد center. یک مقدارِ دیگر هم هست: justify که خط‌ها را کش می‌دهد تا هر دو لبه صاف شوند؛ روی یک پاراگراف امتحانش کن و ببین لبهٔ چپِ متن هم صاف می‌شود.

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

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

فایلِ HTML همان است که در بخش ۱ نوشتی. این هم styles.cssِ کامل:

/* styles.css */
@font-face {
  font-family: "Vazirmatn";
  src: url("https://cdn.jsdelivr.net/npm/@fontsource/vazirmatn/files/vazirmatn-arabic-400-normal.woff2") format("woff2");
  font-weight: 400;
}

@font-face {
  font-family: "Vazirmatn";
  src: url("https://cdn.jsdelivr.net/npm/@fontsource/vazirmatn/files/vazirmatn-arabic-700-normal.woff2") format("woff2");
  font-weight: 700;
}

* {
  box-sizing: border-box;
}

body {
  font-family: "Vazirmatn", Tahoma, sans-serif;
  background-color: #f6edda;
  color: #2c2114;
}

.post {
  font-size: 1.125rem;
  line-height: 1.9;
  padding: 24px;
}

.post h1 {
  font-weight: 700;
  text-align: center;
}

.lead {
  font-weight: 700;
}

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

کلمه تلفظ به حروف فارسی یعنی چه
typography تایپوگرافی هنرِ چیدنِ متن طوری که خوب خوانده شود
font-family فونت‌فَمیلی فونتِ متن، معمولاً به‌شکلِ یک stack ‌ی fallback
stack اِستَک فهرستِ فونت‌ها به‌ترتیبِ اولویت
@font-face اَت‌فونت‌فیس قاعده‌ای که یک فایلِ فونت را بار می‌کند و به آن اسم می‌دهد
font-size فونت‌سایز اندازهٔ متن
line-height لاین‌هایت فاصلهٔ بین خط‌ها
font-weight فونت‌ویت درشتی/کلفتیِ متن (400 عادی، 700 پُر)
text-align تکست‌اِلاین چینشِ متن (right, left, center, justify)

تمرین‌ها

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

در فصل بعد#

الان متن‌هایت خوانا و مرتب‌اند. تا اینجا جعبه‌ها همیشه به‌همان شکلی که مرورگر می‌چیند زیر هم و کنار هم می‌نشستند. فصل بعد سراغ همین جریان عادی می‌رویم: چرا بعضی عناصر زیر هم می‌آیند و بعضی کنار هم، چطور با display این رفتار را عوض کنی، یک غافلگیریِ معروف به‌نامِ margin collapsing، و direction که برای صفحه‌های فارسی حیاتی است.

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

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