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

آخر این فصل میتوانی:
- فرق واحدِ مطلق (
px) و نسبی (%،rem،em) را بگویی - برای اندازهٔ فونت
remرا درست بهکار ببری و بفهمی چرا معمولاً بهترین انتخاب است - یک رنگ را با
hex،rgb()،hsl()وoklch()بنویسی - با
opacityچیزی را نیمهشفاف کنی
قبل از شروع#
- از فصل ۴:
box-sizing،padding،border،marginو واحدpxکه آنجا سرسری معرفی شد؛ اینجا کاملش میکنیم. - از فصل ۳:
cascade— یادت هست که وقتی دو قاعده به یک چیز مقدار میدهند، آخری برنده است؟ در بخشoklchدقیقاً به همین تکیه میکنیم. - از فصل ۲:
classو از فصل ۱:colorوbackground-color.
مثل همیشه فقط یک مرورگر لازم داری، یا فقط همین آزمایشگاه.
۱. واحد: مطلق در برابر نسبی#
هر اندازهای در CSS — پهنا، فاصله، اندازهٔ فونت — یک عدد است بهعلاوهٔ یک واحد. واحدها دو دستهاند.
واحدِ مطلق، یعنی px: همیشه همانقدر است، به هیچچیزِ دیگر وابسته نیست. 16px یعنی ۱۶ نقطه، تمام. صریح و قابلپیشبینی است.
واحدِ نسبی، یعنی درصدی یا برابری از یک چیزِ دیگر. مثلاً % نسبت به فضای در دسترس است. اگر به یک جعبه بگویی width: 50%، یعنی نصفِ عرضِ چیزی که داخلش نشسته. بیا سریع ببینیمش؛ در آزمایشگاه یک جعبهٔ آزمایشی بساز:
.demo {
width: 50%;
background-color: #2a6b93;
height: 40px;
}
✅ چک کن: جعبه دقیقاً تا نصفِ عرضِ صفحه کشیده میشود. حالا پنجرهٔ مرورگر (یا پنلِ آزمایشگاه) را پهنتر و باریکتر کن — جعبه هم با آن بزرگ و کوچک میشود، چون 50% به عرضِ صفحه وابسته است. اگر width را 200px بگذاری، هرچه پنجره را عوض کنی جعبه ثابت میماند. این تفاوتِ مطلق و نسبی است.
۲. rem و em: دو واحدِ نسبی برای فونت#
برای اندازهٔ فونت دو واحدِ نسبیِ مهم داریم که خیلی شبیهاند و دقیقاً همین شباهت، تازهکارها را گیر میاندازد:
emنسبت به font-size ی است که خودِ عنصر دارد (که معمولاً از پدرش به ارث برده).1.25emیعنی «۱٫۲۵ برابرِ فونتِ فعلی».remنسبت به font-size ی است که ریشهٔ صفحه (<html>) دارد. آن یکی هرچقدر تودرتو باشی ثابت میماند.
مرورگر بهطور پیشفرض به ریشه 16px میدهد. پس 1rem تقریباً همیشه 16px است، 1.5rem میشود 24px، و این عددها هرجای صفحه که باشی عوض نمیشوند. em اما بستگی دارد به اینکه کجا نشستهای — و همینجاست که ماجرا جالب میشود.
💡 نکته: چرا اصلاً
remبهجایpx؟ چون بعضی کاربران برای راحتیِ چشم، اندازهٔ فونتِ پیشفرضِ مرورگرشان را بزرگتر میکنند. اگر فونتها را باremنوشته باشی، همهشان با آن تنظیم بزرگ میشوند و صفحهات خوانا میماند. اگر باpxنوشته باشی، ثابت میمانند و آن کاربر را نادیده گرفتهای.
بیا این را روی نظرهای واقعی ببینیم. اول ساختارِ رشتهنظرها را در HTML بنویس — دقت کن هر جواب، یک <article class="comment"> است داخلِ نظرِ قبلی:
<!-- 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="comment">
<p class="name">نیما</p>
<p class="tag">نویسنده</p>
<p>این مقاله خیلی بهدردم خورد، ممنون!</p>
<p class="time">۲ ساعت پیش</p>
<article class="comment">
<p class="name">سارا</p>
<p>موافقم، مخصوصاً بخش آخرش را دوست داشتم.</p>
<p class="time">۱ ساعت پیش</p>
<article class="comment">
<p class="name">نیما</p>
<p>خوشحالم که مفید بود.</p>
<p class="time">۴۰ دقیقه پیش</p>
</article>
</article>
</article>
</body>
</html>
و یک استایلِ ساده بهش بده تا هر نظر یک جعبهٔ سفید با کمی فاصله باشد:
.comment {
background-color: #ffffff;
border: 1px solid #d9cbaa;
padding: 16px;
margin-top: 16px;
}
✅ چک کن: سه نظر میبینی که هرکدام کمی تو رفته و زیرِ نظرِ قبلی نشستهاند — چون هر جواب داخلِ نظرِ قبلی است و padding اش آن را تو میبَرد. اندازهٔ متنِ همه یکسان است. حالا با em این آرامش را بههم میزنیم.
۳. وقتی em از دستت در میرود#
فرض کن میخواهی نظرها کمی بزرگتر از حالت عادی باشند. طبیعی است که بنویسی «۱٫۲۵ برابرِ فونت». به .comment این را بده:
.comment {
font-size: 1.25em;
background-color: #ffffff;
border: 1px solid #d9cbaa;
padding: 16px;
margin-top: 16px;
}
به صفحه نگاه کن. نظرِ اول کمی بزرگتر شده — خوب است. ولی جوابِ زیرش از آن هم بزرگتر است، و جوابِ سومی که از همه تودرتوتر است، درشتِ درشت شده. هرچه عمیقتر، بزرگتر. تو که همهجا یک عدد نوشتی، پس چرا؟
🔧 اگر کار نکرد: این عمدی است و باید همین بزرگشدنِ پلکانی را ببینی. دلیلش در تعریفِ
emاست:emنسبت به فونتِ خودِ عنصر است، و هر نظر فونتش را از نظرِ پدرش میگیرد. پس محاسبه اینطور زنجیر میشود: نظرِ اول1.25 × 16 = 20؛ نظرِ دوم1.25 ×۲۰= 25؛ نظرِ سوم1.25 ×۲۵= 31. هر لایه1.25برابرِ لایهٔ قبل میشود، نه ۱٫۲۵ برابرِ ریشه — به این میگویند compounding، مثل گلولهٔ برفی که هر دور بزرگتر میشود.
راهِ حل این است که بهجای «۱٫۲۵ برابرِ پدرم» بگویی «۱٫۲۵ برابرِ ریشه» — یعنی em را با rem عوض کنی. rem هرچقدر هم تودرتو باشی به همان ریشه نگاه میکند، پس دیگر زنجیر نمیشود:
.comment {
font-size: 1rem;
background-color: #ffffff;
border: 1px solid #d9cbaa;
padding: 16px;
margin-top: 16px;
}
✅ چک کن: حالا هر سه نظر دقیقاً هماندازهاند، مهم نیست چقدر تودرتو باشند. مقدار را به 1.25rem عوض کن: همه با هم بزرگ میشوند ولی باز هم هماندازه میمانند — چون هر سه از یک ریشه اندازه میگیرند. این است فرقِ rem و em.
💡 نکته: پس
emبیفایده است؟ نه.emدقیقاً وقتی خوب است که بخواهی چیزی نسبت به فونتِ همان عنصر مقیاس بگیرد — مثلاً padding ی که باید با بزرگشدنِ متن، بزرگ شود. قاعدهٔ سرانگشتی: برای اندازهٔ فونتrem، برای فاصلههایی که باید با فونت هماهنگ بمانندem.
قبل از ادامه، جواب بده: اگر ریشه 16px باشد و یک عنصر font-size: 2rem بگیرد، چند پیکسل میشود؟ (جواب: 32px — و مهم نیست کجای صفحه باشد.)
۴. رنگ: سه راه برای نوشتنِ یک رنگ#
تا حالا رنگها را با کدهایی مثل #2a6b93 نوشتیم. به این hex میگویند: یک # و شش رقمِ شانزدهشانزدهی که بهترتیب مقدارِ قرمز، سبز و آبیاند. کوتاه است ولی برای آدم خواندنی نیست — با نگاه به #2a6b93 نمیفهمی چه رنگی است.

همان رنگ را میشود جورِ دیگر هم نوشت. rgb() همان سه مقدارِ قرمز/سبز/آبی را با عددِ معمولی (۰ تا ۲۵۵) میگیرد:
.name {
color: rgb(42 107 147);
}
rgb(42 107 147) دقیقاً همان #2a6b93 است، فقط خواناتر. ولی هنوز هم با دیدنِ سه عدد نمیفهمی رنگ چیست. اینجاست که hsl() کمک میکند: رنگ را با سه چیزِ قابلتصور میگوید — hue (نوعِ رنگ، ۰ تا ۳۶۰ روی چرخِ رنگ)، saturation (چقدر پُررنگ) و lightness (چقدر روشن):
.name {
color: hsl(203 56% 37%);
}
✅ چک کن: هر سه نوشته — #2a6b93، rgb(42 107 147) و hsl(203 56% 37%) — یک رنگِ آبیِ یکسان میدهند؛ یکییکی امتحان کن و ببین اسمِ نظرها عوض نمیشود. مزیتِ hsl وقتی معلوم میشود که بخواهی رنگ را تنظیم کنی: عددِ اولِ hsl را از 203 به 10 ببر تا آبی به قرمز برود، یا عددِ آخر را از 37% به 70% ببر تا همان آبی روشنتر شود. با hex این کارها حدسوگمان است؛ با hsl مثل چرخاندنِ چند پیچ است.
۵. oklch و یک fallback واقعی#
یک راهِ تازهتر و بهترِ نوشتنِ رنگ هم هست: oklch(). مثل hsl با روشنی و رنگ و شدت کار میکند، ولی طوری ساخته شده که به چشمِ آدم نزدیکتر است — وقتی روشنی را کموزیاد میکنی، تغییرش یکنواخت بهنظر میرسد، نه پرشی. و به رنگهای زندهتری دسترسی میدهد که در rgb قدیمی جا نمیشدند.
oklch امروز در مرورگرهای امروزی کار میکند، ولی ممکن است کاربری مرورگرِ خیلی قدیمی داشته باشد که آن را نشناسد. برای اینجور جاها یک fallback مینویسیم: اول رنگ را به یک شکلِ قدیمی و مطمئن (hex) مینویسیم، بعد در خطِ بعد به oklch. به برچسبِ «نویسنده» این را بده:
.tag {
color: #ffffff;
background-color: #a36207; /* fallback: rang-e sRGB */
background-color: oklch(55% 0.11 66); /* modern: gamut-e vasi'-tar */
padding: 2px 8px;
}
اینجا دقیقاً از cascadeِ فصل ۳ استفاده میکنیم: دو قاعده به یک property مقدار میدهند و آخری برنده است — بهشرطی که مرورگر آن را بفهمد. مرورگرِ امروزی هر دو خط را میخواند و چون oklch را میفهمد، خطِ دومی برنده میشود. مرورگرِ خیلی قدیمی خطِ oklch را نمیفهمد و دورش میاندازد، پس همان hex برایش میماند. هیچکس رنگِ خراب نمیبیند.
✅ چک کن: برچسبِ «نویسنده» یک پسزمینهٔ نارنجیطلایی میگیرد. خطِ oklch را موقتاً پاک کن و ببین رنگ به همان نارنجیِ hex برمیگردد — همان چیزی که یک مرورگرِ قدیمی میبیند.
⚠️ مواظب باش: ترتیب مهم است. اگر
hexرا بعد ازoklchبنویسی، مرورگرِ امروزی هم آخری را برمیدارد و رنگِ بهتر را از دست میدهی. همیشه fallback ی اول، نسخهٔ بهتر بعد.
نوشتنِ این نسخههای مختلفِ یک رنگ، دقیقاً جایی است که AI میتواند کارت را راه بیندازد:
🤖 با AI: از دستیار AI ات بخواه یک رنگِ
hex(مثلاً#a36207) را بهhslوoklchتبدیل کند. بعد هر سه را در آزمایشگاه امتحان کن و با چشمت چک کن که واقعاً یک رنگاند — چون AI در تبدیلِ رنگ گاهی عددِ کمی پرت میدهد، و تنها راهِ مطمئنشدن، دیدنِ نتیجه در مرورگر است، نه اعتماد به عددِ AI.
۶. opacity: نیمهشفاف کردن#
گاهی میخواهی چیزی کمرنگ و کماهمیت بهنظر برسد، مثل زمانِ زیر هر نظر. opacity کلِ عنصر را شفاف میکند: 1 یعنی کاملاً توپُر، 0 یعنی کاملاً نامرئی، و بینشان نیمهشفاف. به زمانها این را بده:
.time {
color: #2c2114;
opacity: 0.55;
}
✅ چک کن: زمانها («۲ ساعت پیش» و بقیه) کمرنگ و محو شدهاند و دیگر با متنِ اصلی رقابت نمیکنند. عدد 0.55 را به 0.2 ببر تا تقریباً ناپدید شوند، بعد به 1 تا کاملاً برگردند.
کد کاملِ این فصل#
فایلِ HTML همان است که در بخش ۲ نوشتی. این هم styles.cssِ کامل:
/* styles.css */
* {
box-sizing: border-box;
}
body {
background-color: #f6edda;
}
.comment {
font-size: 1rem;
background-color: #ffffff;
border: 1px solid #d9cbaa;
padding: 16px;
margin-top: 16px;
}
.name {
color: #2a6b93;
}
.tag {
color: #ffffff;
background-color: #a36207; /* fallback: rang-e sRGB */
background-color: oklch(55% 0.11 66); /* modern: gamut-e vasi'-tar */
padding: 2px 8px;
}
.time {
color: #2c2114;
opacity: 0.55;
}
واژههای تازهٔ این فصل#
| کلمه | تلفظ به حروف فارسی | یعنی چه |
|---|---|---|
| unit | یونیت | واحدِ اندازه که بعد از عدد میآید (px, rem, …) |
| px | پیکسل | واحدِ مطلق؛ همیشه ثابت |
| rem | رِم | واحدِ نسبی به font-size ی ریشهٔ صفحه (<html>) |
| em | اِم | واحدِ نسبی به font-size ی خودِ عنصر |
| font-size | فونتسایز | اندازهٔ متن |
| hex | هِکس | رنگ بهشکلِ # و شش رقم شانزدهشانزدهی |
| rgb | آرجیبی | رنگ با سه مقدارِ قرمز، سبز، آبی |
| hsl | اچاسال | رنگ با hue، saturation، lightness |
| oklch | اُکِلسیاچ | راهِ تازهترِ نوشتن رنگ، نزدیکتر به چشمِ آدم |
| fallback | فالبک | نسخهٔ پشتیبان برای وقتی مرورگر نسخهٔ اصلی را نمیفهمد |
| opacity | اوپَسیتی | میزانِ شفافیتِ کلِ عنصر، از 0 تا 1 |
تمرینها
اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.
در فصل بعد#
الان واحدها و رنگ را در دست داری. تا اینجا متنها با فونتِ پیشفرضِ مرورگر بودند — که مخصوصاً برای فارسی همیشه زیبا و خوانا نیست. فصل بعد سراغ تایپوگرافی میرویم: با font-family فونت را عوض میکنیم، با @font-face یک فونتِ فارسیِ درستوحسابی را بار میکنیم، و با line-height به متنِ فارسی جای نفسکشیدن میدهیم.
به آخر این فصل رسیدی!
اگر ساختی و جواب داد، این دکمه مال توست.