طراحی حالت تاریک و روشن با CSS
حالت تاریک و روشن (Dark Mode و Light Mode) یکی از ویژگیهای مهم تجربه کاربری مدرن است. این مقاله به طور جامع روشهای پیادهسازی، اصول طراحی، نکات دسترسپذیری و نمونههای عملی با CSS و JavaScript را توضیح میدهد تا بتوانید پوستهای منعطف، قابل نگهداری و کاربرپسند بسازید.
چرا حالت تاریک و روشن مهم است؟
- کاهش خستگی چشم در محیطهای کمنور
- افزایش جذابیت بصری و انعطافپذیری طراحی
- پشتیبانی از ترجیحات سیستمی کاربر (prefers-color-scheme)
- بهبود طول عمر باتری برای نمایشگرهای OLED
مبانی و منطق طراحی (Theme architecture)
بهترین روش این است که همه رنگها را با CSS Custom Properties (متغیرهای CSS) تعریف کنید و سپس در هر حالت (روشن/تاریک) مقادیر متفاوت را مقداردهی کنید. این رویکرد نگهداری و تغییر رنگها را ساده میکند و به راحتی با مدیا کوئریها و کلاسها قابل ترکیب است.
پیادهسازی پایه با CSS Variables و prefers-color-scheme
/* Base (default) variables */:root {
--bg: #ffffff;
--text: #111827;
--muted: #6b7280;
--primary: #2563eb;
--surface: #f8fafc;
}
/* Dark mode via system preference */@media (prefers-color-scheme: dark) {
:root {
--bg: #0b1220;
--text: #e6eef8;
--muted: #9aa6b2;
--primary: #60a5fa;
--surface: #071025;
}
}
body {
background: var(--bg);
color: var(--text);
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
transition: background-color 250ms ease, color 250ms ease;
}این کد پایهای متغیرهای رنگ را تعریف میکند و با @media (prefers-color-scheme: dark) به مرورگر اجازه میدهد تا بر اساس تنظیمات سیستمی کاربر رنگهای تاریک را اعمال کند. استفاده از var(--...) باعث میشود تغییر رنگ در کل پروژه سریع و متمرکز باشد.
تغییر دستی بین حالتها (Toggle) با JavaScript
<button id="theme-toggle" aria-pressed="false">Toggle theme</button>
<script>
const root = document.documentElement;
const btn = document.getElementById('theme-toggle');
function applyTheme(theme) {
if (theme === 'dark') {
root.setAttribute('data-theme', 'dark');
btn.setAttribute('aria-pressed', 'true');
} else {
root.removeAttribute('data-theme');
btn.setAttribute('aria-pressed', 'false');
}
localStorage.setItem('theme', theme);
}
btn.addEventListener('click', () => {
const current = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
applyTheme(current === 'dark' ? 'light' : 'dark');
});
// On load: respect saved preference or system
const saved = localStorage.getItem('theme');
if (saved) applyTheme(saved);
</script>در این مثال یک دکمه ساده داریم که با کلیک، حالت را بین dark و light تغییر میدهد. وضعیت در localStorage ذخیره میشود تا در بازدیدهای بعدی نیز حفظ شود. همچنین از aria-pressed برای بهبود دسترسپذیری استفاده کردیم.
ترکیب با CSS (data-theme)
/* Theme override when user toggles */:root[data-theme="dark"] {
--bg: #0b1220;
--text: #e6eef8;
--muted: #9aa6b2;
--primary: #60a5fa;
--surface: #071025;
}با استفاده از صفت data-theme روی :root میتوانید اولویت دسترسی کاربر را نسبت به ترجیح سیستمی اعمال کنید. این اجازه میدهد تا تنظیمات ذخیرهشده کاربر بر تنظیمات سیستمی غلبه داشته باشد.
دسترسپذیری و کنتراست
تضمین کنتراست مناسب بین متن و پسزمینه حیاتی است. طبق استاندارد WCAG حداقل نسبت کنتراست برای متنهای معمولی 4.5:1 است. برای بررسی کنتراست از ابزارهایی مثل Lighthouse، Contrast Checker یا افزونههای مرورگر استفاده کنید.
- از رنگهای با کنتراست کافی برای متن و دکمهها استفاده کنید.
- برای المانهای کلیدی حالت فوکوس واضح و قابل مشاهده تعریف کنید.
- تصاویر و آیکونها را برای هر تم بررسی کنید (مثلاً آیکونها در تم تاریک ممکن است نیاز به نسخه روشنتر داشته باشند).
احترام به prefers-reduced-motion
/* Respect reduced motion setting */@media (prefers-reduced-motion: reduce) {
* {
transition: none !important;
animation: none !important;
}
}این قطعه تضمین میکند که کاربرانی که از انیمیشن اجتناب میکنند تجربهای آرامتر خواهند داشت. همیشه انیمیشنها را طوری طراحی کنید که اختلال ایجاد نکنند و برای حالتهای حساس قابل غیرفعالشدن باشند.
الگوها و نکات عملی
- نامگذاری متغیرها با رویکرد معنایی (مثلاً –bg, –surface, –text, –accent) نگهداری را آسانتر میکند.
- برای عناصر سطحی (Card، Modal) از متغیرهای جداگانه استفاده کنید تا سایه و رنگ سطح تغییرپذیر باشد.
- عکسها و SVGها: اگر از SVG با رنگ خط استفاده میکنید، از
currentColorبهره ببرید تا آیکونها خودکار تغییر رنگ دهند. - آزمون کاربری در محیطهای مختلف نور و دستگاهها بخشی از فرایند تحویل است.
نمونه جدول متغیرهای پیشنهادی برای دو تم
| Variable | Light | Dark |
|---|---|---|
| –bg | #ffffff | #0b1220 |
| –surface | #f8fafc | #071025 |
| –text | #111827 | #e6eef8 |
| –muted | #6b7280 | #9aa6b2 |
| –primary | #2563eb | #60a5fa |
نمونه کامل پیشنهادی با دسترسپذیری بهتر
<button id="theme-toggle" aria-label="Toggle dark mode" aria-pressed="false">
<span class="sr-only">Toggle theme</span>
🌗
</button>
<script>
const root = document.documentElement;
const btn = document.getElementById('theme-toggle');
function setThemeAttr(theme) {
if (theme === 'dark') {
root.setAttribute('data-theme', 'dark');
btn.setAttribute('aria-pressed', 'true');
} else {
root.removeAttribute('data-theme');
btn.setAttribute('aria-pressed', 'false');
}
}
function getPreferred() {
const saved = localStorage.getItem('theme');
if (saved) return saved;
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
// Initialize
setThemeAttr(getPreferred());
btn.addEventListener('click', () => {
const newTheme = (root.getAttribute('data-theme') === 'dark') ? 'light' : 'dark';
setThemeAttr(newTheme);
localStorage.setItem('theme', newTheme);
});
</script>این نسخه بهبود یافته شامل برچسبهای دسترسپذیری (ARIA) است و اولویت را به تنظیم ذخیرهشده کاربر میدهد. همچنین از آیکون متنی برای نمایش وضعیت استفاده شده تا برای خوانندگان صفحهخوان قابل تفسیر باشد.
خلاصه و جمعبندی
طراحی حالت تاریک و روشن با استفاده از CSS Variables، مدیا کوئریهای سیستمی و یک مکانیزم ساده ذخیرهسازی ترجیح کاربر، نسبتاً ساده و بسیار موثر است. نکات کلیدی: متغیرهای معنایی، بررسی کنتراست، احترام به prefers-reduced-motion و فراهم کردن کنترل دستی با دسترسپذیری مناسب. با پیروی از این الگوها میتوانید تجربهای یکپارچه و قابل اعتماد در تمام دستگاهها فراهم کنید.
آیا این مطلب برای شما مفید بود ؟




