ساخت مقادیر قابل‌استفاده مجدد: تعریف Custom Properties و var()

وارد فصل شانزدهم شدیم؛ فصلی که به CSS Custom Properties (که معمولاً به‌عنوان CSS Variables هم شناخته می‌شن) اختصاص داره. در فصل ۱۵ (درس ۱۵-۳)، با تابع var() آشنا شدیم، ولی گفتیم جزئیات کامل تعریف و مدیریت این متغیرها رو، به این فصل موکول می‌کنیم. حالا وقتشه از پایه شروع کنیم و ببینیم دقیقاً چطور یک Custom Property تعریف و استفاده می‌شه.

مشکل: مقادیر تکراری در سراسر یک پروژه

.button {
  background-color: #2c3e50;
}

.header {
  color: #2c3e50;
}

.link {
  border-color: #2c3e50;
}

در یک پروژه واقعی، معمولاً یک رنگ، فاصله، یا اندازه خاص، ده‌ها بار، در جاهای مختلف فایل CSS، تکرار می‌شه. مشکل اینجاست: اگه بعداً بخوایم این رنگ رو تغییر بدیم، باید همه این موارد رو، یکی‌یکی، پیدا و ویرایش کنیم؛ کاری که هم زمان‌بره و هم مستعد خطاست (ممکنه یک مورد رو فراموش کنیم).

Custom Property چیست؟

Custom Property (ویژگی سفارشی CSS)، یک متغیره که خودمون، با یک نام دلخواه، تعریف می‌کنیم و یک مقدار بهش می‌دیم؛ بعد، هرجایی که به همون مقدار نیاز داشتیم، به‌جای تکرار مقدار خام، به همون متغیر ارجاع می‌دیم.

Syntax تعریف: دو خط تیره در ابتدای نام

.container {
  --main-color: #2c3e50;
}

هر Custom Property، باید با دو خط تیره (--) شروع بشه؛ این پیشوند، دقیقاً همون چیزیه که به مرورگر می‌گه: «این یک Property معمولی مثل color یا margin نیست، بلکه یک متغیر تعریف‌شده توسط خود توسعه‌دهنده‌ست».

استفاده از مقدار تعریف‌شده با var()

.container {
  --main-color: #2c3e50;
  color: var(--main-color);
}

برای خوندن مقدار یک Custom Property، همون‌طور که در درس ۱۵-۳ دیدیم، از تابع var() استفاده می‌کنیم. مرورگر، در لحظه محاسبه استایل، مقدار --main-color رو، دقیقاً همون‌جایی که var(--main-color) نوشته شده، جایگزین می‌کنه.

حل مشکل اولیه با یک متغیر مرکزی

:root {
  --brand-color: #2c3e50;
}

.button {
  background-color: var(--brand-color);
}

.header {
  color: var(--brand-color);
}

.link {
  border-color: var(--brand-color);
}

حالا، با تعریف یک متغیر مرکزی، اگه بخوایم رنگ برند رو تغییر بدیم، فقط کافیه یک خط رو (تعریف --brand-color) ویرایش کنیم؛ همه جاهایی که از این متغیر استفاده کردن، به‌طور خودکار، به‌روزرسانی می‌شن. این رویکرد، مستقیماً به همون فلسفه‌ای برمی‌گرده که در فصل ۱ (External CSS) هم دیدیم: تمرکز مدیریت در یک نقطه، به‌جای تکرار در چند جا.

چرا معمولاً روی :root تعریف می‌شود؟

:root {
  --spacing-md: 16px;
}

همون‌طور که در فصل ۳ (درس ۳-۵) با Pseudo-class به اسم :root آشنا شدیم، این Selector، به بالاترین عنصر ساختار سند (معادل تگ html) اشاره می‌کنه. تعریف متغیرها روی :root، به این معنیه که این مقادیر، از طریق Inheritance (که در فصل ۲ دیدیم)، به تمام عناصر صفحه، سرایت می‌کنن؛ یعنی هر Selectorای، در هر عمقی از HTML، می‌تونه بدون محدودیت، از این متغیرها استفاده کنه.

تعریف متغیر در یک Scope محدودتر

.card {
  --card-padding: 20px;
  padding: var(--card-padding);
}

لازم نیست همه متغیرها، حتماً روی :root تعریف بشن. یک متغیر، می‌تونه داخل هر Selectorای تعریف بشه؛ در این حالت، فقط همون عنصر و فرزندانش (به‌خاطر Inheritance)، به این متغیر دسترسی دارن. این موضوع رو، با جزئیات کامل، در درس‌های بعدی همین فصل (Scope و Inheritance) بررسی می‌کنیم.

هر مقدار CSS، می‌تواند داخل یک Custom Property ذخیره شود

:root {
  --main-color: #2c3e50;
  --spacing-unit: 8px;
  --font-stack: "Vazirmatn", sans-serif;
  --card-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
  --transition-speed: 0.3s;
}

Custom Propertyها، محدود به رنگ نیستن؛ می‌شه هر نوع مقداری (اندازه، فونت، سایه، زمان و مشابه‌ها) رو، داخل یک متغیر ذخیره کرد.

استفاده از یک متغیر داخل یک عبارت calc()

:root {
  --spacing-unit: 8px;
}

.box {
  padding: calc(var(--spacing-unit) * 2);
  margin-bottom: calc(var(--spacing-unit) * 3);
}

می‌شه Custom Propertyها رو، همون‌طور که در درس ۱۵-۱ با calc() دیدیم، داخل عبارات ریاضی هم استفاده کرد. در این مثال، با تغییر فقط یک عدد پایه (--spacing-unit)، تمام فاصله‌گذاری‌های وابسته بهش، به‌طور نسبی و هماهنگ، تغییر می‌کنن.

حساسیت به حروف بزرگ و کوچک

:root {
  --Main-Color: red;
}

.box {
  color: var(--main-color); /* این کار نمی‌کند؛ نام دقیقاً باید یکسان باشد */
}

یک نکته فنی مهم: برخلاف بسیاری از نام‌های Property استاندارد CSS (که به حروف بزرگ و کوچک حساس نیستن)، نام Custom Propertyها، کاملاً Case-sensitive (حساس به حروف بزرگ/کوچک) هستن؛ یعنی --Main-Color و --main-color، دو متغیر کاملاً متفاوت و جدا از هم محسوب می‌شن.

یک مثال کامل و جامع

:root {
  --primary-color: #1a73e8;
  --border-radius: 8px;
  --spacing-unit: 8px;
}

.card {
  background-color: white;
  border: 1px solid var(--primary-color);
  border-radius: var(--border-radius);
  padding: calc(var(--spacing-unit) * 2);
}

.card-title {
  color: var(--primary-color);
}

در این مثال، سه متغیر مرکزی، در چند جای مختلف یک کامپوننت، به‌طور هماهنگ، استفاده شدن؛ تغییر هرکدوم از این سه مقدار پایه، بدون نیاز به جست‌وجو و ویرایش دستی در چند خط جدا، بلافاصله در تمام جاهای استفاده‌شده، اعمال می‌شه.

نکات مهم

  • هر Custom Property، باید با دو خط تیره (--) شروع شود؛ مقدارش با var() قابل بازخوانی است.
  • تعریف متغیرها روی :root، به‌خاطر Inheritance، دسترسی سراسری به آن‌ها را در کل سند فراهم می‌کند.
  • نام Custom Propertyها، برخلاف اکثر Propertyهای استاندارد CSS، کاملاً به حروف بزرگ و کوچک حساس است.

اشتباهات رایج

  • فراموش کردن دو خط تیره در ابتدای نام متغیر، که باعث می‌شود مرورگر آن را یک Property معمولی (و نامعتبر) در نظر بگیرد.
  • ناهماهنگی در حروف بزرگ و کوچک بین تعریف و استفاده از یک متغیر، که باعث می‌شود مقدار آن اصلاً خوانده نشود.
  • تعریف مقادیر پرکاربرد به‌صورت مستقیم و تکراری در چند Selector، به‌جای استفاده از یک Custom Property مرکزی.

جمع‌بندی

Custom Properties، با Syntax دو خط تیره در ابتدای نام (مثل --main-color) تعریف می‌شوند و مقدارشان، با تابع var()، در هر جای دیگری از CSS، قابل بازخوانی است. تعریف این متغیرها روی :root، دسترسی سراسری در کل سند را، به‌خاطر Inheritance، فراهم می‌کند؛ این رویکرد، مشکل تکرار مقادیر در سراسر یک پروژه را حل می‌کند و مدیریت متمرکز رنگ‌ها، فاصله‌ها و سایر مقادیر رایج را، بسیار ساده‌تر می‌سازد.