زمان محاسبهٔ متغیرهای CSS رو خودت تعیین کن
خلاصهٔ کاملتر
جیک آرچیبالد تو مقالهٔ تازهش سراغ یه جزئیات ریز ولی مهم از CSS رفته: اینکه مقدار یه custom property (همون متغیرهای --something) دقیقاً کِی حساب میشه. به گفتهٔ نویسنده، جواب پیشفرض معمولاً اونی نیست که انتظار داری و مستقیم روی استایل نهایی اثر میذاره.
حالت پیشفرض اینه که یه متغیر ثبتنشده انگار syntax: '*' داره، یعنی مقدارش فقط به شکل یه token stream (رشتهای از توکنهای خام و حسابنشده) نگه داشته میشه. برای همین تو کد زیر sibling-index() سر جای تعریف اجرا نمیشه، بلکه لحظهای که var() توی فرزند بازش میکنه حساب میشه و چون اون پاراگراف اولین فرزنده، عدد ۱ درمیاد:
.second-item {
--index: sibling-index();
& > :first-child {
scale: var(--index);
}
}همین رفتار تو getComputedStyle() هم دیده میشه: روی اون div خودِ رشتهٔ "sibling-index()" برمیگرده، نه یه عدد. حالا کافیه همون متغیر رو ثبت کنی تا زمان محاسبه جابهجا شه:
@property --index {
syntax: '<number>';
inherits: true;
initial-value: 0;
}با syntax: '' مقدار همونجای تعریف به عدد ۲ تبدیل میشه، فرزند هم همون ۲ رو میگیره و getComputedStyle() این بار "2" رو لاگ میکنه.
نویسنده میگه این ماجرا فقط مخصوص sibling-index() نیست: واحدهای نسبی فونت مثل em و ex و ch و cap و lh و واحدهای container query مثل cqw و cqi و cqb هم به همین زمانبندی حساسن. URLها هم درگیرن، البته یهکم فرق دارن. تو CSS آدرسها موقع computed-value نسبت به base URL همون استایلشیت resolve میشن، پس اگه یه متغیر token stream تو یه فایل تعریف شه و تو فایل دیگهای var() شه، آدرس نسبت به فایل مصرفکننده حساب میشه. ثبتش با syntax: '' اونو به فایل تعریفکننده پین میکنه.
یه استثنای مهم هم هست: خودِ var() جزو arbitrary substitution functionها حساب میشه (کنار if() و attr() و ident()) و بدون توجه به syntax متغیر، بلافاصله جایگزین میشه. برای همین تو چیزی مثل calc(sibling-index() * var(--multiplier)) مقدار --multiplier همونجای تعریف برداشته میشه و اگه فرزند --multiplier: 3 خودشو داشته باشه، کلاً نادیده میمونه. نویسنده میگه خودش هم تا امروز این جزئیات رو نصفهنیمه بلد بوده.
نکات کلیدی:
- متغیر ثبتنشده مثل syntax: '*' رفتار میکنه و مقدارش به شکل token stream خام میمونه
- ثبت با @property و syntax: '' مقدار رو سر جای تعریف حساب میکنه، پس sibling-index() بهجای ۱ عدد ۲ میده
- واحدهای em, ch, lh و cqw, cqi هم به همین زمان محاسبه وابستهن
- syntax: '' آدرس رو به استایلشیت تعریفکننده پین میکنه
- var(), if(), attr(), ident() فوری جایگزین میشن، برای همین --multiplier روی فرزند بیاثره




