متغیرهای CSS؛ کلید انعطاف پذیری و طراحی مدرن
- متغیرهای CSS چه هستند و چگونه کار می کنند
- مکانیزم var() در عمل
- حوزه (Scope) و ارث بری—کلید قدرت متغیرها
- حوزه سراسری (Global Scope) با :root
- حوزه محلی (Local Scope) برای انعطاف پذیری
- نحوه کار Cascade با متغیرها
- مقادیر پشتیبان (Fallback Values)—بیمه طراحی شما
- چرا fallback ها حیاتی هستند
- ساختار صحیح fallback
- استفاده از @supports برای مرورگر های قدیمی
- به روزرسانی زنده با JavaScript
- قدرت setProperty()
- مثال عملی: تغییر تم رنگی
- مقایسه عملکرد روش های JS
- استفاده در Vue.js برای رابط کاربری واکنش گرا
- پشتیبانی مرورگرها
- استراتژی های سازگاری
- ملاحظات عملکرد—چه چیزی را باید بدانید
- واقعیت عملکرد
- تله های عملکردی
- بهترین شیوه ها برای عملکرد بهینه
- پیاده سازی حالت تاریک (Dark Mode)
- الگوی استاندارد
- استفاده از prefers-color-scheme
- متغیرها در سیستم های طراحی (Design Systems)
- ساختاردهی هوشمندانه
- نام گذاری معنایی (Semantic Naming)
- مستندسازی برای تیم
- مقایسه با پیش پردازنده ها (Sass/Less)
- تفاوت های بنیادین
- چه زمانی از کدام استفاده کنید
- تله های رایج و راه های حل آن ها
- تله ۱: فراموش کردن حوزه (Scope)
- تله ۲: استفاده بیش از حد
- تله ۳: عدم استفاده از fallback در محیط های بحرانی
- تله ۴: آپدیت های مکرر متغیرهای سراسری
- چک لیست عملی برای پیاده سازی
- قبل از شروع
- حین پیاده سازی
- تست و بهینه سازی
- نگهداری
- نتیجه گیری: تبدیل دانش به کاربرد عملی
فرض کنید سایتی با صدها صفحه دارید و مدیر بازاریابی تصمیم می گیرد رنگ برند شرکت را تغییر دهد. بدون متغیرهای CSS، باید به طور دستی هر کد رنگ را در ده ها یا حتی صدها فایل جستجو و جایگزین کنید. این فرآیند پرخطا، وقت گیر و غیرقابل تحمل است. اما با متغیرهای CSS، فقط یک خط کد را تغییر می دهید و تمام سایت در چند ثانیه به روز می شود.
متغیرهای CSS (که به آن ها Custom Properties یا خواص سفارشی هم می گویند) ابزاری انقلابی هستند که از سال ۲۰۱۷ در تمام مرورگرهای مدرن پشتیبانی می شوند. این ابزار به شما قدرت می دهد تا مقادیر تکراری را یک بار تعریف کنید و در سراسر پروژه استفاده کنید. در این مقاله از فاتحی اسکول، به صورت دقیق به این موضوع می پردازیم و تمام نکات پیشرفته را با مثال های ملموس بررسی می کنیم.
متغیرهای CSS چه هستند و چگونه کار می کنند
متغیرهای CSS برچسب های سفارشی هستند که خودتان برای عادت های طراحی تان می سازید. هر مقداری که ممکن است تکرار شود—از رنگ های برند گرفته تا فاصله ها، اندازه فونت ها یا حتی مقادیر انیمیشن—را می توانید در یک متغیر ذخیره کنید.
ساختار اصلی:
:root {
--primary-color: #۰۰۷bff;
--spacing-unit: ۱۶px;
--border-radius: ۸px;
}
Code language: CSS (css)در این کد، دو خط تیره (--) ابتدای نام متغیر نشان می دهد این یک «خاصیت سفارشی» است. مرورگر این مقادیر را در حافظه نگه می دارد و هر جا که var(--primary-color) را ببیند، به طور خودکار آن را با #007bff جایگزین می کند.
مکانیزم var() در عمل
تابع var() کلید دسترسی به متغیرهاست. سه نکته حیاتی درباره آن باید بدانید:
- نام متغیر باید دقیقاً مطابقت داشته باشد:
--primary-colorو--Primary-colorدو چیز متفاوت هستند. - مقادیر پشتیبان (fallback): می توانید مقدار دوم را به عنوان بک آپ اضافه کنید:
var(--color, #000). - تکه تکه کردن مقادیر: متغیرها می توانند قسمتی از یک مقدار باشند، مثلاً:
var(--spacing-unit) auto.
مثال کاربردی:
button {
background-color: var(--primary-color, #۳۴۹۸db);
padding: calc(var(--spacing-unit) / ۲) var(--spacing-unit);
border-radius: var(--border-radius);
}
Code language: CSS (css)اگر --primary-color تعریف نشده باشد، دکمه به جای آن از #3498db استفاده می کند. این پشتوانه سازی امنیت طراحی شما را تضمین می کند.
حوزه (Scope) و ارث بری—کلید قدرت متغیرها
حوزه سراسری (Global Scope) با :root
وقتی متغیرها را در :root تعریف می کنید، در دسترس تمام المان های صفحه قرار می گیرند. :root همان تگ <html> را هدف می گیرد، اما اولویت بالاتری دارد. این بهترین جا برای تعریف «طراحی توکن» (design tokens) مانند رنگ های برند، تایپوگرافی و فاصله هاست.
نمونه عملی:
:root {
--color-primary: #۲۵۶۳eb;
--color-secondary: #۱۰b۹۸۱;
--font-sans: 'Inter', system-ui, sans-serif;
--shadow-lg: ۰ ۱۰px ۱۵px -۳px rgba(۰, ۰, ۰, ۰.۱);
}
Code language: CSS (css)حوزه محلی (Local Scope) برای انعطاف پذیری
می توانید متغیرها را در انتخابگرهای خاص تعریف کنید تا فقط در آن بخش کار کنند. این ویژگی برای کامپوننت های مستقل یا تم های موضعی بسیار ارزشمند است.
مثال کارت محصول:
.product-card {
--card-bg: #ffffff;
--card-border: #e۵e۷eb;
background: var(--card-bg);
border: ۱px solid var(--card-border);
padding: var(--spacing-unit);
}
/* تم تاریک برای کارت خاص */
.product-card.dark {
--card-bg: #۱f۲۹۳۷;
--card-border: #۳۷۴۱۵۱;
}
Code language: CSS (css)متغیرهای محلی از والدین ارث می برند. اگر --card-bg در .product-card.dark نباشد، مرورگر به .product-card نگاه می کند، اگر آنجا هم نباشد، به :root برمی گردد.
نحوه کار Cascade با متغیرها
سیستم Cascade (آبشاری) CSS روی متغیرها هم اعمال می شود. وقتی یک متغیر هم در :root و هم در یک کلاس محلی تعریف شود، مرورگر نزدیک ترین تعریف را به المان استفاده می کند.
مثال تم روشن/تاریک:
:root {
--text-color: #۰۰۰۰۰۰; /* حالت پیش فرض روشن */
}
[data-theme="dark"] {
--text-color: #ffffff; /* بازنویسی در حالت تاریک */
}
body {
color: var(--text-color);
}
Code language: CSS (css)همین مکانیزم ساده باعث می شود پیاده سازی دکمه تغییر تم بدون نیاز به CSS جدید ممکن شود.
مقادیر پشتیبان (Fallback Values)—بیمه طراحی شما
چرا fallback ها حیاتی هستند
متغیرها ممکن است به دلایلی وجود نداشته باشند: شاید مرورگر قدیمی است، شاید جاوااسکریپت بارگذاری نشده، یا شاید کد را اشتباه تایپ کرده اید. بدون fallback، استایل کلاً اعمال نمی شود و المان شما بی شکل می ماند.
ساختار صحیح fallback
روش اشتباه: var(--color, --backup-color, blue) ← این کار نمی کند.
روش صحیح (nested): var(--color, var(--backup-color, blue)) ← درست است.
مثال عملی:
.alert {
background-color: var(--alert-bg, var(--info-bg, #eff6ff));
border-left: ۴px solid var(--alert-border, #۳b82f6);
padding: var(--spacing-unit);
}
Code language: CSS (css)در این کد، اگر --alert-bg نبود، از --info-bg استفاده می شود، اگر آن هم نبود، به #eff6ff برمی گردد. این زنجیره پشتیبان اطمینان می دهد که هیچ وقت بدون استایل نمی مانید.
استفاده از @supports برای مرورگر های قدیمی
برای مرورگر هایی که CSS Variables را پشتیبانی نمی کنند (مثل IE)، از feature query استفاده کنید:
.button {
background-color: #۳۴۹۸db; /* Fallback برای IE */
}
@supports (--css: variables) {
.button {
background-color: var(--primary-color, #۳۴۹۸db);
}
}
Code language: CSS (css)این روش تضمین می کند که در IE۱۱ به جای متغیر، مستقیماً از #3498db استفاده شود.
به روزرسانی زنده با JavaScript
قدرت setProperty()
برخلاف پیش پردازنده ها (مثل Sass)، متغیرهای CSS در زمان اجرا (runtime) قابل تغییر هستند. این قابلیت را با setProperty() در اختیار می گیرد.
ساختار:
element.style.setProperty('--variable-name', 'new-value', 'optional-priority');
Code language: JavaScript (javascript)مثال عملی: تغییر تم رنگی
HTML:
<button id="theme-toggle">تم را تغییر ده</button>
Code language: HTML, XML (xml)CSS:
:root {
--primary-color: #۰۰۷bff;
}
body {
background-color: var(--primary-color);
transition: background-color ۰.۳s ease;
}
Code language: CSS (css)JavaScript:
const button = document.getElementById('theme-toggle');
const root = document.documentElement;
let isDefault = true;
button.addEventListener('click', () => {
const newColor = isDefault ? '#ff۴۵۰۰' : '#۰۰۷bff';
root.style.setProperty('--primary-color', newColor);
isDefault = !isDefault;
});
Code language: JavaScript (javascript)کلیک روی دکمه، رنگ پس زمینه را بدون نیاز به ریلود صفحه تغییر می دهد.
مقایسه عملکرد روش های JS
یک تست jsPerf نشان داد که:
- Safari:
element.style = "--color: green"سریع تر است - Firefox:
setProperty()بسیار سریع تر است - Chrome: تفاوت چندانی ندارد
اما setProperty() در تمام مرورگرها پایدارتر و استاندارد است، پس استفاده از آن توصیه می شود.
استفاده در Vue.js برای رابط کاربری واکنش گرا
در Vue.js می توانید از watch برای به روزرسانی خودکار متغیرها استفاده کنید:
<script setup>
import { ref, watch } from 'vue'
const isDark = ref(false)
watch(isDark, (newValue) => {
const root = document.documentElement
const newBg = newValue ? '#۱a۱a۱a' : '#ffffff'
root.style.setProperty('--bg-color', newBg)
})
</script>
Code language: HTML, XML (xml)هر تغییر در isDark بلافاصله تم سایت را به روز می کند.
پشتیبانی مرورگرها
تا آگوست ۲۰۲۵، CSS Variables در ۹۸% مرورگرهای مدرن پشتیبانی می شوند. این یعنی می توانید بدون نگرانی از آن ها استفاده کنید.
جدول دقیق پشتیبانی:
- Chrome: از نسخه ۴۹+ (کامل)
- Firefox: از نسخه ۳۱+ (کامل)
- Safari: از نسخه ۱۰+ (کامل)، نسخه ۹.۱ (جزئی)
- Edge: از نسخه ۱۶+ (کامل)، نسخه ۱۵ (جزئی)
- IE: بدون پشتیبانی
- Opera: از نسخه ۳۶+ (کامل)
استراتژی های سازگاری
۱. Fallback های دستی:
.button {
background: #۳۴۹۸db; /* برای IE */
background: var(--primary-color, #۳۴۹۸db); /* برای مدرن */
}
Code language: CSS (css)۲. استفاده از @supports:
@supports (--css: variables) {
/* استایل های پیشرفته فقط برای مرورگرهای پشتیبانی کننده */
.card {
background: var(--surface-bg);
box-shadow: var(--shadow-lg);
}
}
Code language: CSS (css)ملاحظات عملکرد—چه چیزی را باید بدانید
واقعیت عملکرد
متغیرهای CSS در زمان رندر محاسبه می شوند. این قدرت آن هاست، اما می تواند در صورت استفاده نادرست مشکل ساز شود.
تله های عملکردی
۱. استفاده بیش از حد در انیمیشن ها:
/* ❌ BAD: این باعث بازمحاسبه در هر فریم می شود */
.animated {
transition: all ۰.۳s;
transform: var(--transform-value);
}
Code language: CSS (css)۲. تودرتوی بیش از حد:
/* ❌ BAD: زمان پردازش را افزایش می دهد */
.box {
padding: var(--spacing, var(--base-spacing, ۱۰px));
}
Code language: CSS (css)۳. تغییر متغیرهای سراسری در تکرارهای زیاد: هر بار که متغیر :root را با JS تغییر دهید، مروربر باید تمام المان هایی که از آن استفاده می کنند را دوباره استایل دهی کند.
بهترین شیوه ها برای عملکرد بهینه
✅ استفاده محتاط از calc():
:root {
--spacing-unit: ۱۶px;
--spacing-lg: calc(var(--spacing-unit) * ۲); /* فقط یک محاسبه */
}
Code language: CSS (css)✅ محدود کردن انیمیشن ها به transform و opacity:
/* ✅ GOOD: این ها از GPU استفاده می کنند */
.smooth {
transition: transform ۰.۳s, opacity ۰.۳s;
transform: translateY(var(--offset, ۰));
}
Code language: CSS (css)✅ به روزرسانی دسته ای با requestAnimationFrame:
// ✅ GOOD: برای تغییرات مکرر
requestAnimationFrame(() => {
root.style.setProperty('--x', x);
root.style.setProperty('--y', y);
});
Code language: JavaScript (javascript)تست های عملکرد نشان داده اند که استفاده صحیح از متغیرها تأثیر چشمگیری روی سرعت رندر ندارد و حتی می تواند با کاهش تکرار کد، بهبودی ایجاد کند.
پیاده سازی حالت تاریک (Dark Mode)
الگوی استاندارد
حالت تاریک محبوب ترین کاربرد متغیرهاست. مراحل ساده است:
مرحله ۱: تعریف متغیرهای تم:
:root {
--bg-color: #ffffff;
--text-color: #۰۰۰۰۰۰;
--card-bg: #f۳f۴f۶;
}
[data-theme="dark"] {
--bg-color: #۱a۱a۱a;
--text-color: #ffffff;
--card-bg: #۲d۲d۲d;
}
Code language: CSS (css)مرحله ۲: استفاده در استایل ها:
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color ۰.۳s, color ۰.۳s;
}
.card {
background-color: var(--card-bg);
padding: var(--spacing-unit);
}
Code language: CSS (css)مرحله ۳: تغییر تم با JS:
const toggleDarkMode = () => {
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
const newTheme = isDark ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme); // ذخیره ترجیحات کاربر
};
Code language: JavaScript (javascript)این روش حتی در Next.js با پکیج هایی مثل next-themes بهینه تر شده است.
استفاده از prefers-color-scheme
برای احترام به ترجیحات سیستمی کاربر:
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #۱a۱a۱a;
--text-color: #ffffff;
}
}
Code language: CSS (css)اما توجه داشته باشید که این روزها بیشتر سایت ها دکمه دستی تم را ترجیح می دهند چون به کاربر کنترل بیشتری می دهد.
متغیرها در سیستم های طراحی (Design Systems)
ساختاردهی هوشمندانه
در پروژه های بزرگ، سازمان دهی متغیرها کلیدی است.
نمونه ساختار:
:root {
/* رنگ ها */
--color-primary: #۳۴۹۸db;
--color-primary-light: #۵dade۲;
--color-primary-dark: #۲۹۸۰b۹;
/* تایپوگرافی */
--font-family-base: 'Inter', sans-serif;
--font-size-xs: ۰.۷۵rem;
--font-size-sm: ۰.۸۷۵rem;
--font-size-base: ۱rem;
--font-size-lg: ۱.۱۲۵rem;
--font-size-xl: ۱.۲۵rem;
/* فاصله ها */
--spacing-xs: ۰.۲۵rem;
--spacing-sm: ۰.۵rem;
--spacing-md: ۱rem;
--spacing-lg: ۱.۵rem;
--spacing-xl: ۲rem;
/* سایه ها */
--shadow-sm: ۰ ۱px ۲px ۰ rgba(۰, ۰, ۰, ۰.۰۵);
--shadow-md: ۰ ۴px ۶px -۱px rgba(۰, ۰, ۰, ۰.۱);
--shadow-lg: ۰ ۱۰px ۱۵px -۳px rgba(۰, ۰, ۰, ۰.۱);
}
Code language: CSS (css)نام گذاری معنایی (Semantic Naming)
نام متغیر را بر اساس کاربرد انتخاب کنید، نه مقدار:
✅ خوب:
--color-surface: #ffffff;
--color-text-primary: #۰۰۰۰۰۰;
Code language: CSS (css)❌ بد:
--color-white: #ffffff;
--color-black: #۰۰۰۰۰۰;
Code language: CSS (css)چرا؟ چون در تم تاریک، --color-white ممکن است سیاه شود و نام آن گمراه کننده می شود.
مستندسازی برای تیم
در پروژه های تیمی، حتماً متغیرها را در style guide مستند کنید:
/*
* Design Tokens
* رنگ های اصلی برند—فقط اینجا تغییر کنید
* --color-primary: برای دکمه های CTA و لینک ها
* --color-secondary: برای تگ ها و برچسب ها
*/
:root {
--color-primary: #۲۵۶۳eb;
--color-secondary: #۱۰b۹۸۱;
}
Code language: CSS (css)این کار از ایجاد متغیرهای تکراری جلوگیری می کند و هماهنگی تیم را حفظ می کند.
مقایسه با پیش پردازنده ها (Sass/Less)
تفاوت های بنیادین
| ویژگی | CSS Variables | Sass/Less Variables |
|---|---|---|
| زمان ارزیابی | زمان اجرا (runtime) | زمان کامپایل |
| دسترسی JS | ✅ مستقیم با setProperty() | ❌ غیرممکن |
| Scope | Cascading (CSS) | Nested (Sass) |
| نیاز به build tool | ❌ ندارد | ✅ دارد |
| پشتیبانی مرورگر | مدرن ها (۹۸%) | همه (پس از کامپایل) |
چه زمانی از کدام استفاده کنید
استفاده از CSS Variables:
- تم های داینامیک (Dark Mode)
- سفارشی سازی کاربر
- واکنش به رویدادهای زنده
- پروژه هایی که build tool ندارند
استفاده از Sass Variables:
- پروژه هایی که باید در IE۱۱ کار کنند
- محاسبات پیچیده ریاضی
- توابع و لوپ های پیشرفته
- کتابخانه هایی که قبل از ۲۰۱۷ ساخته شده اند
نکته مهم: می توانید از هر دو استفاده کنید! Sass variables برای محاسبات، و CSS Variables برای تم های داینامیک.
تله های رایج و راه های حل آن ها
تله ۱: فراموش کردن حوزه (Scope)
مشکل:
.sidebar {
--sidebar-width: ۲۵۰px;
}
.main-content {
width: var(--sidebar-width); /* ❌ کار نمی کند! */
}
Code language: CSS (css)حل:
:root {
--sidebar-width: ۲۵۰px; /* ✅ در root تعریف کنید */
}
Code language: CSS (css)تله ۲: استفاده بیش از حد
مشکل: تعریف متغیر برای هر مقدار کوچک باعث پیچیدگی بی مورد می شود.
حل: فقط مقادیری را متغیر کنید که:
- در چند جا تکرار می شوند
- احتمال تغییر دارند
- برای تم سازی مهم هستند
تله ۳: عدم استفاده از fallback در محیط های بحرانی
مشکل:
button {
background: var(--btn-bg); /* اگر این متغیر نباشد، دکمه شفاف می شود! */
}
Code language: CSS (css)حل:
button {
background: var(--btn-bg, #۰۰۷bff); /* ✅ همیشه پشتیبان داشته باشید */
}
Code language: CSS (css)تله ۴: آپدیت های مکرر متغیرهای سراسری
مشکل: تغییر متغیر :root در یک loop باعث رندر مجدد سنگین می شود.
حل: از requestAnimationFrame یا محدود کردن تغییرات به المان های کوچک استفاده کنید.
چک لیست عملی برای پیاده سازی
قبل از شروع
- تمام مقادیر تکراری را لیست کنید
- تصمیم بگیرید کدام مقادیر باید قابل تغییر باشند
- ساختار پوشه ها و فایل های CSS را مشخص کنید
حین پیاده سازی
- متغیرها را فقط در
:rootیا انتخابگرهای والد تعریف کنید - برای هر متغیر حیاتی، fallback مناسب اضافه کنید
- نام ها را معنایی و توصیفی بنویسید
- مستندسازی را در کامنت ها اضافه کنید
تست و بهینه سازی
- در Chrome DevTools قسمت، tab “CSS Overview” را بررسی کنید
- از Coverage استفاده کنید تا متغیرهای استفاده نشده را پیدا کنید
- در مرورگر های قدیمی (یا حالت IE۱۱ در DevTools) تست کنید
- Performance tab را بررسی کنید تا رندر مجدد ناخواسته نداشته باشید
نگهداری
- هر فصل، متغیرهای اضافی را حذف کنید
- مقادیر را با طراح سیستم هماهنگ کنید
- تغییرات را در CHANGELOG مستند کنید
نتیجه گیری: تبدیل دانش به کاربرد عملی
متغیرهای CSS دیگر یک ویژگی اختیاری نیستند—آن ها پایه طراحی وب مدرن هستند. با این ابزار:
- توسعه سریع تر می شود (کمتر تایپ می کنید)
- نگهداری آسان تر می شود (یک جا تغییر می دهید)
- انعطاف پذیری بیشتر دارید (تم داینامیک)
- همکاری تیمی بهبود می یابد (مستندات واضح)
اما قدرت مسئولیت می آورد. استفاده بی رویه از متغیرها می تواند کد را پیچیده کند. همیشه از fallback استفاده کنید، حوزه را مدیریت کنید و عملکرد را تست کنید.
پیشنهاد من: همین امروز یک پروژه کوچک را باز کنید و سه متغیر برای رنگ های اصلی بسازید. آن ها را در کل پروژه جایگزین کنید و تجربه سهولت تغییر را لمس کنید. این اولین قدم به سمت یک سیستم طراحی مقیاس پذیر است.
در دنیایی که کاربران انتظار شخصی سازی و سرعت دارند، متغیرهای CSS کلید بقای شما در صنعت هستند. آن ها را جدی بگیرید و مهارت تسلط بر آن ها را در رزومتان درج کنید. آینده وب، آینده ای متغیر است.