ویژگی تصویر

طراحی حالت تاریک و روشن با CSS

  /  CSS   /  طراحی حالت تاریک و روشن با 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 بهره ببرید تا آیکون‌ها خودکار تغییر رنگ دهند.
  • آزمون کاربری در محیط‌های مختلف نور و دستگاه‌ها بخشی از فرایند تحویل است.

نمونه جدول متغیرهای پیشنهادی برای دو تم

VariableLightDark
–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 و فراهم کردن کنترل دستی با دسترس‌پذیری مناسب. با پیروی از این الگوها می‌توانید تجربه‌ای یکپارچه و قابل اعتماد در تمام دستگاه‌ها فراهم کنید.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: