وقتی متغیر تعریف نشده: Fallback Values

در درس قبل، Custom Properties رو تعریف کردیم، ولی همیشه فرض کردیم که متغیر، از قبل، مقداری داره. حالا وقتشه ببینیم اگه یک متغیر، به هر دلیلی، تعریف نشده باشه یا مقدارش نامعتبر باشه، چه اتفاقی می‌افته؛ و چطور می‌شه، با Fallback Value، از این وضعیت جلوگیری کرد.

مشکل: متغیر تعریف‌نشده

.box {
  color: var(--text-color);
}

اگه متغیر --text-color، در هیچ‌جای CSS تعریف نشده باشه، مقدار var(--text-color)، به یک مقدار معتبر تبدیل نمی‌شه؛ در نتیجه، Property به اسم color، عملاً نامعتبر در نظر گرفته می‌شه. نتیجه این می‌شه که مرورگر، به مقدار پیش‌فرض همون Property (که در فصل ۲، با Initial Value آشنا شدیم) برمی‌گرده؛ نه یک خطای کلی در کل فایل CSS.

راه‌حل: پارامتر دوم var()

.box {
  color: var(--text-color, black);
}

همون‌طور که در درس ۱۵-۳ به‌طور مقدماتی دیدیم، تابع var()، یک پارامتر دوم و اختیاری می‌پذیره: یک Fallback Value (مقدار جایگزین). اگه --text-color تعریف نشده باشه، مرورگر، به‌جای رها کردن Property، از همین مقدار جایگزین (black) استفاده می‌کنه.

Fallback فقط در نبود متغیر فعال می‌شود، نه هر زمان دلخواه

:root {
  --text-color: navy;
}

.box {
  color: var(--text-color, black); /* نتیجه: navy، نه black */
}

این نکته، دقیقاً همونیه که در درس ۱۵-۳ هم تأکید کردیم: Fallback، فقط وقتی فعال می‌شه که متغیر، اصلاً وجود نداشته باشه (یا نامعتبر باشه)؛ نه هر وقت که بخوایم یک مقدار «امن‌تر» رو ترجیح بدیم. در این مثال، چون --text-color واقعاً تعریف شده، همون مقدار (navy) استفاده می‌شه.

Fallback به‌عنوان یک متغیر دیگر

.box {
  color: var(--custom-text-color, var(--default-text-color, black));
}

مقدار Fallback، لازم نیست حتماً یک مقدار خام (مثل black) باشه؛ می‌تونه خودش هم یک var() دیگه باشه. در این مثال، اگه --custom-text-color تعریف نشده باشه، مرورگر، سراغ --default-text-color می‌ره؛ و اگه اونم تعریف نشده بود، در نهایت، به black می‌رسه. این تکنیک، یک زنجیره از Fallbackها می‌سازه که، هر لایه، یک سطح امنیت بیشتر اضافه می‌کنه.

کاربرد عملی: کامپوننت‌های قابل‌تنظیم از بیرون

.button {
  background-color: var(--button-bg, #2c3e50);
  color: var(--button-text, white);
  padding: var(--button-padding, 10px 20px);
}
<button class="button">دکمه پیش‌فرض</button>

<button class="button" style="--button-bg: crimson;">دکمه سفارشی</button>

یکی از کاربردهای بسیار عملی Fallback، ساخت کامپوننت‌هایی‌ست که، به‌طور پیش‌فرض، ظاهر مشخصی دارن، ولی از بیرون (مثلاً با یک استایل Inline، یا با تعریف مجدد همون متغیر روی یک Class دیگه)، قابل‌شخصی‌سازی هستن؛ بدون این‌که مجبور باشیم برای هر حالت، یک Class کاملاً جدا بنویسیم. در این مثال، دکمه اول، چون --button-bg تعریف نکرده، از رنگ پیش‌فرض (#2c3e50) استفاده می‌کنه؛ دکمه دوم، چون این متغیر رو مستقیماً روی خودش (با یک استایل Inline) تعریف کرده، رنگ سفارشی (crimson) رو می‌گیره.

تفاوت Fallback با مقدار پیش‌فرض Initial Value یک Property

این نکته، مستقیماً به فصل ۲ (Initial Value) برمی‌گرده و مهمه که این دو مفهوم رو با هم قاطی نکنیم:

مفهوم توضیح
Initial Value (فصل ۲) مقدار پیش‌فرض استاندارد یک Property، وقتی هیچ مقداری (حتی نامعتبر) براش تعریف نشده
Fallback Value (این درس) مقداری که فقط داخل تابع var()، برای زمانی که خود متغیر ارجاع‌شده، تعریف نشده، مشخص می‌کنیم

یک نکته مهم: Fallback فقط برای «نبود» متغیر است، نه برای مقادیر نامعتبر داخل خود آن (در برخی موارد)

:root {
  --spacing: not-a-valid-value;
}

.box {
  padding: var(--spacing, 16px);
}

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

یک مثال کامل: تم‌بندی با Fallbackهای چندلایه

:root {
  --brand-color: #1a73e8;
}

.card {
  border-color: var(--card-border-color, var(--brand-color, #ccc));
  background-color: var(--card-bg, white);
}

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

نکات مهم

  • پارامتر دوم var()، یک Fallback Value است که فقط وقتی متغیر اصلی تعریف نشده باشد، فعال می‌شود.
  • Fallback می‌تواند خودش هم یک var() دیگر باشد و یک زنجیره چندلایه از مقادیر پشتیبان بسازد.
  • Fallback در var()، با Initial Value یک Property (که در فصل ۲ دیدیم) مفهوماً متفاوت است؛ اولی مخصوص نبود متغیر است، دومی مخصوص نبود هرگونه مقدار برای خود Property.

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

  • تصور اینکه Fallback، هر وقت بخواهیم یک مقدار «امن‌تر» را ترجیح دهیم فعال می‌شود؛ در حالی که فقط در نبود کامل متغیر فعال می‌شود.
  • فراموش کردن تعریف Fallback در متغیرهایی که ممکن است، بسته به شرایط، تعریف نشده باشند (مثل متغیرهای قابل‌تنظیم از بیرون یک کامپوننت).
  • تعریف Fallbackهایی که، از نظر نوع مقدار، با Property مقصد ناسازگارند.

جمع‌بندی

Fallback Value، به‌عنوان پارامتر دوم تابع var()، یک مقدار جایگزین برای زمانی فراهم می‌کند که خود Custom Property، تعریف نشده باشد؛ این مقدار جایگزین، می‌تواند خودش هم یک var() دیگر باشد و یک زنجیره چندلایه از مقادیر پشتیبان بسازد. این قابلیت، مخصوصاً برای ساخت کامپوننت‌های قابل‌شخصی‌سازی از بیرون، یا سیستم‌های طراحی با چند سطح از متغیرهای عمومی و خاص، بسیار کاربردی است.