حالت تاریک

ویژگی color-scheme نشان می‌دهد صفحه‌تان از کدام آرایش رنگ‌ها (مثل روشن یا تیره) پشتیبانی می‌کند. این کار به مرورگر اطلاع می‌دهد که می‌تواند به‌طور خودکار عناصر میانای کاربر بومی (مانند نوارهای پیمایش، کنترل‌های فرم، و پس‌زمینه بوم پیش‌فرض) را با طراحی سایت شما مطابقت دهد و به حداقل رساندن چشمک‌های سفید درطول بارگیری اولیه کمک کند.

پیاده‌سازی

۱. اعلام طرح‌های پشتیبانی‌شده در HTML

الزامی: برای کمک به جلوگیری از «فلش محتوای بدون زمینه» (FOUC)، برچسب <meta> را در <head> خود قرار دهید تا مطمئن شوید مرورگر قبل‌از شروع به پردازش می‌داند از کدام زمینه‌ها پشتیبانی می‌کنید. اگرچه این برچسب <meta> با تنظیم زودهنگام رنگ اولیه بوم به جلوگیری از FOUC کمک می‌کند، ممکن است چشمک زدن را در همه مرورگرها یا شرایط بارگیری به‌طور کامل حذف نکند.

<!-- MANDATORY: Declare support for both light and dark themes -->
<meta name="color-scheme" content="light dark">

۲. اعمال کردن آرایش رنگ‌های سراسر صفحه به CSS :root یا html

اجباری: ویژگی color-scheme را روی عنصر html یا شبه‌کلاس :root اعمال کنید. مرورگرها به‌طور خاص به عنصر ریشه نگاه می‌کنند تا طرح زمینه را برای کل نمای دید تعیین کنند—ازجمله نوارهای پیمایش ریشه و پس‌زمینه اولیه «بوم». اگر فقط برای body اعمال شود، این سطوح رابط کاربری سراسری ممکن است در حالت روشن باقی بمانند زیرا body بافتار پردازشی پنجره را کنترل نمی‌کند.

/* MANDATORY: Apply color-scheme to :root or html for viewport-wide theming */
:root {
  /* MANDATORY: Automatically adapt native UI to user system preferences */
  color-scheme: light dark;
}

۳. تعریف کردن نشان‌های رنگ روشن و تیره

می‌توانید از تابع light-dark() برای تعریف کردن کدهای رنگی که به‌طور خودکار با مقادیر مختلف color-scheme سازگار می‌شوند استفاده کنید.

توصیه می‌شود مقادیر رنگ خام را نیز در ویژگی‌های سفارشی جداگانه نگه دارید، که ترکیب آن‌ها را به روش‌های مختلف آسان‌تر می‌کند (و درصورت نیاز، رفتار بازگشتی را آسان‌تر می‌کند).

برای کنترل بیشتر بر رنگ‌های میانای کاربر داخلی مانند accent-color یا scrollbar-color، نویسندگان می‌توانند به‌صورت اختیاری رنگ‌های پویا خود را بااستفاده از ویژگی‌های سفارشی و/یا تابع light-dark() اضافه کنند. این تابع به‌طور خودکار رنگ صحیح را براساس color-scheme محاسبه‌شده عنصر انتخاب می‌کند و نیاز به پرسمان‌های رسانه‌ای زائد را ازبین می‌برد، اما برای پیاده‌سازی پایه لازم نیست.

:root {
  --color-brand-light: oklch(45% 0.23 270);
  --color-brand-dark: oklch(85% 0.15 210);
  --color-brand-text-light: white;
  --color-brand-text-dark: oklch(40% 0.23 270);

  --color-brand: light-dark(var(--color-brand-light), var(--color-brand-dark));
  --color-brand-text: light-dark(var(--color-brand-text-light), var(--color-brand-text-dark));

  /* MANDATORY: Automatically adapt native UI to user system preferences */
  color-scheme: light dark;
}

button.primary {
  /* These automatically adapt to color scheme */
  background-color: var(--color-brand);
  color: var(--color-brand-text);
}

اختیاری: تعدادی رنگ سیستم دردسترس است که به‌طور خودکار با طرح رنگ استفاده‌شده (و دیگر حالت‌های رنگ، مثلاً رنگ‌های اجباری) سازگار می‌شوند، مانند canvas،‏ canvastext،‏ accentcolor (بررسی پشتیبانی)،‏ buttonborder، و غیره. این رنگ‌ها معمولاً بسیار محدود هستند و نمی‌توانند مفید باشند، به‌جز در موارد بسیار خاصی که باید دقیقاً با رابط کاربری مرورگر پیش‌فرض مطابقت داشته باشند یا به‌عنوان رنگ‌های جایگزین/پیش‌فرض استفاده شوند.

اختیاری: جفت‌های رنگ را با بافت تطبیق دهید

حتی هنگام لغو کردن پیش‌فرض سیستم، استفاده از پُرسمان رسانه‌ای prefers-color-scheme برای تعریف کردن جفت‌های رنگی متفاوت که رنگ‌های مرورگر و Chrome سیستم‌عامل اطراف صفحه (یا صفحه اطراف، وقتی صفحه به‌عنوان iframe استفاده می‌شود) را درنظر می‌گیرد می‌تواند مفید باشد.

برای مثال، وقتی تنظیم سیستم dark است، از زمینه روشن کمی کم‌نورتر استفاده کنید، یا وقتی تنظیم سیستم light است، از زمینه تیره با کنتراست بیشتر استفاده کنید تا صفحه ازنظر بصری تحت‌تأثیر واسط کاربری اطراف قرار نگیرد.

سفارشی‌سازی دقیق واسط کاربر مرورگر

تنظیم color-scheme ازقبل واسط کاربر مرورگر را با آرایش رنگ‌های استفاده‌شده تطبیق می‌دهد، اما این کار از پیش‌فرض‌های سیستم‌عامل و/یا رنگ‌های سیستم استفاده می‌کند که ممکن است کاملاً با طراحی وب‌سایت مطابقت نداشته باشد. مرورگرهای نو چندین قلاب سفارشی‌سازی دقیق برای این موارد ارائه می‌دهند. کنترل‌های بومی را صرفاً برای سفارشی‌سازی ظاهر آن‌ها بدون استفاده کامل از قلاب‌های سفارشی‌سازی که مرورگرهای مدرن ارائه می‌دهند، دوباره پیاده‌سازی نکنید.

تنظیم رنگ ثانویه

برخی‌از واسط‌های کاربر مرورگر (مثلاً چارگوش‌های انتخاب علامت‌زده‌شده یا لغزنده‌ها) از رنگ ثانویه استفاده می‌کنند. این ویژگی به‌طور پیش‌فرض به تنظیمات سیستم‌عامل ارجاع می‌دهد، اما می‌توانید از ویژگی accent-color برای تنظیم آن روی رنگی که با صفحه هماهنگی بیشتری دارد، مانند رنگ نمانام صفحه، استفاده کنید.

html {
  accent-color: light-dark(var(--color-accent-light), var(--color-accent-dark));
}

مشکلاتی که باید هنگام استفاده از accent-color از آن‌ها مطلع باشید

پرداخت accent-color در مرورگر متفاوت است. برای نشانگرهایی که معمولاً روی پس‌زمینه رنگ ثانویه کشیده می‌شوند، مانند علامت‌های چارگوش انتخاب و نقطه‌های دکمه رادیویی، مرورگرها ممکن است رفتارهای متفاوتی اعمال کنند:

  • Chromium و Firefox معمولاً رنگ نشانگر متضادی را انتخاب می‌کنند.
  • Safari ممکن است به‌جای آن، نشانگر سفید را در حالت روشن یا نشانگر سیاه را در حالت تیره حفظ کند و درعین‌حال رنگ ثانویه پشت آن را تغییر دهد. این تنظیم همیشه کنتراست کافی برای هر رنگ ارائه‌شده فراهم نمی‌کند، بنابراین ترکیب‌های مهم را در Safari آزمایش کنید، ازجمله طرح‌های رنگی روشن و تیره. فرض نکنید که Safari به‌طور خودکار رنگ نشانگری را انتخاب می‌کند که بهترین کنتراست را ارائه می‌دهد.

رنگ‌های نوار پیمایش

می‌توانید از scrollbar-color همراه با light-dark() استفاده کنید تا رنگ‌های سفارشی نوار پیمایش را تنظیم کنید که با طرح رنگ استفاده‌شده سازگار شوند.

:root {
  --color-scrollbar-track: light-dark(#eee, #222);
  --color-scrollbar-thumb: light-dark(#999, #666);
  scrollbar-color: var(--color-scrollbar-thumb) var(--color-scrollbar-track);
}

مشکلاتی که باید هنگام استفاده از scrollbar-color از آن‌ها آگاه باشید

  • scrollbar-color را پویانمایی یا گذار نکنید. اشکال WebKit باعث می‌شود نوار پیمایش هربار که scrollbar-color تغییر می‌کند چشمک بزند.
  • در macOS، ویژگی‌های scrollbar-color (استاندارد) و ::-webkit-scrollbar (قدیمی) به‌طور پیش‌فرض نادیده گرفته می‌شوند زیرا macOS از نوارهای پیمایش «هم‌پوشانی» بومی استفاده می‌کند. باید رنگ‌های سفارشی را با scrollbar-width (مثلاً thin یا auto) جفت کنید تا macOS را مجبور به ارائه آن‌ها کنید.
  • حتی با اعمال scrollbar-width، نوارهای پیمایش رونهاد macOS به‌طور پیش‌فرض شیار (ناودان) را به‌صورت شفاف پرداز می‌زنند. اگر طراحی به رنگ پس‌زمینه قابل‌مشاهده برای شیار در MacOS نیاز دارد، باید scrollbar-gutter: stable; را روی محفظه قابل‌پیمایش اعمال کنید، اما توجه داشته باشید که این رنگ فقط زمانی ظاهر می‌شود که کاربر نشانگر را روی نوار پیمایش نگه دارد.
  • حتی با scrollbar-gutter: stable، ممکن است قطعه در MacOS شفاف باشد. نمایان بودن دکمه لغزنده نباید به رنگ شیار بستگی داشته باشد.

سفارشی‌سازی بیشتر

اکثر واسط‌های کاربر مرورگر شبه‌عنصرهایی را برای سفارشی‌سازی کامل ظاهر آن ارائه می‌دهند، مانند:

  • ::placeholder
  • ::spelling-error
  • ::grammar-error
  • ::selection
  • ::search-text
  • ::target-text
  • ::file-selector-button

می‌توانید از رنگ‌های light-dark() در هریک از این موارد استفاده کنید تا رنگ‌هایی را اعمال کنید که با طرح رنگ استفاده‌شده سازگار شوند.

۴. تصاویر متفاوت برای حالت روشن و تاریک

برای تصاویر CSS، از light-dark() نیز می‌توان برای ارائه مقادیر مختلف تصویر استفاده کرد.

مهم: هر دو مقدار در light-dark() باید از یک نوع باشند. نمی‌توانید رنگ را با تصویر ترکیب کنید. اگر یکی از این دو باید تصویر باشد، از image(<color>) برای پیچیدن مقدار رنگ استفاده کنید.

تشخیص زمینه مبتنی بر JS

بیشتر شاخه‌بندی‌های آرایش رنگ‌ها باید در CSS انجام شود که به‌طور خودکار با تغییرات سازگار می‌شود.

هر JS که matchMedia("(prefers-color-scheme: dark)").matches را می‌خواند باید رویداد change آن را نیز مدیریت کند زیرا اولویت سیستم می‌تواند در هر زمانی تغییر کند.

اختیاری: پیاده‌سازی کلید تغییر وضعیت آرایش رنگ‌ها

اگر می‌خواهید به کاربران اجازه دهید پیش‌فرض سیستم خود را برای این سایت به‌صورت دستی لغو کنند، می‌توانید کلید روشن/خاموش حالت تاریک را پیاده‌سازی کنید. اکثر سایت‌ها به کلید روشن/خاموش دائمی در میانای کاربری سایت نیاز ندارند. معمولاً پیش‌فرض کردن آرایش رنگ‌های سیستم کافی است، و به‌طور اختیاری می‌توان تنظیماتی در سطح تنظیمات جداگانه داشت. برای روال‌های مطلوب درباره پیاده‌سازی کلید «حالت تاریک» (دائمی یا غیردائمی)، به کلیدهای «حالت تاریک» مراجعه کنید.

اختیاری: لغوهای مختص مؤلفه

می‌توانید با تنظیم color-scheme روی عناصر خاص، زمینه سراسری را برای آن‌ها لغو کنید.

برای اطلاعات بیشتر و نکات مهم، به زمینه روشن/تیره مختص مؤلفه مراجعه کنید.

مشکلات شناخته‌شده‌ای که باید از آن‌ها مطلع باشید

مشکلاتی که باید هنگام استفاده از طرح رنگ از آن‌ها آگاه بود

  • Chrome و Firefox از color-scheme برای iframeها پیروی می‌کنند: آن‌ها صفحه‌های جاسازی‌شده را با آرایش رنگ‌های صحیح ارائه می‌دهند و پرسمان رسانه prefers-color-scheme صفحه جاسازی‌شده را طوری تنظیم می‌کنند که color-scheme بافت جاسازی را منعکس کند. Safari این کار را نمی‌کند و prefers-color-scheme را به تنظیمات سیستم حتی در iframeها ارجاع می‌دهد.
    • اگر هم والد و هم iframe را کنترل می‌کنید: طرح‌واره رنگ والد را به‌طور صریح به iframe منتقل کنید — ازطریق پارامتر URL (?theme=dark) در زمان ساخت iframe، یا ازطریق postMessage() (که به شما امکان می‌دهد به تغییرات زمان اجرا نیز واکنش نشان دهید). در iframe، به‌جای تکیه بر prefers-color-scheme، کلاسی را در <html> (و/یا color-scheme در :root) از آن سیگنال تنظیم کنید.
    • اگر فقط صفحه جاسازی‌شده را کنترل می‌کنید: هیچ راه قابل‌اعتمادی برای شناسایی color-scheme بافت جاسازی از داخل iframe در Safari وجود ندارد. پارامتر زمینه صریحی را در میانای برنامه‌سازی کاربردی جاسازی‌شده‌تان (مثلاً رشته پُرسمان یا پروتکل postMessage) نشان دهید و آن را برای جاسازکنندگان مستند کنید.

راهبردهای جایگزین

پشتیبانی مرورگر و جایگزین‌ها برای طرح رنگ

خصوصیت color-scheme ارتقای پیش‌رو است. مرورگرهایی که از آن پشتیبانی نمی‌کنند این ویژگی را نادیده می‌گیرند و از واسط کاربر حالت روشن پیش‌فرض خود استفاده می‌کنند.

برای سازگار شدن با اولویت‌های کاربر در مرورگرهای قدیمی‌تر، از پُرسمان‌های رسانه‌ای prefers-color-scheme استفاده کنید تا وقتی حالت تیره ترجیح داده می‌شود رنگ‌های متفاوتی ارائه شود.

  • از پرسمان رسانه برای روشن کردن ویژگی‌های سفارشی در :root یا html استفاده کنید
  • از به‌کار بردن پرسمان رسانه در مؤلفه‌های تکی خودداری کنید، مگراینکه مؤلفه به نوع بسیار خاصی از سفارشی‌سازی حالت تاریک فراتر از رنگ‌ها نیاز داشته باشد.
:root {
  /* Define brand colors for each mode */
  --color-brand-light: #0056b3;
  --color-brand-dark: #00e5ff;
  --color-brand: var(--color-brand-light);

  /* MANDATORY: Fallback for browsers without light-dark support */
  @media (prefers-color-scheme: dark) {
    --color-brand: var(--color-brand-dark);
  }

  /* Ignored in older browsers */
  color-scheme: light dark;
}

button.primary {
    background-color: var(--color-brand);
}

پشتیبانی مرورگر و بازگشت‌ها برای light-dark()‎

برای مرورگرهایی که از color-scheme پشتیبانی می‌کنند اما هنوز از light-dark() پشتیبانی نمی‌کنند، نسخه‌های روشن و تیره رنگ‌ها باید ابتدا به‌عنوان ویژگی‌های سفارشی تعریف شوند و از پُرسمان رسانه‌ای prefers-color-scheme باید برای تنظیم رنگ‌ها برای حالت مربوطه استفاده شود، مانند مثال زیر:

:root {
  /* Define browser UI accent color for each mode */
  --brand-accent-light: #0056b3;
  --brand-accent-dark: #00e5ff;
  --accent-color: var(--brand-accent-light);

  /* MANDATORY: Fallback for browsers without light-dark support */
  @media (prefers-color-scheme: dark) {
    --accent-color: var(--brand-accent-dark);
  }

  /* OPTIONAL: use light-dark() for more control of built-in UI colors */
  @supports (color: light-dark(white, black)) {
    --accent-color: light-dark(var(--brand-accent-light), var(--brand-accent-dark));
  }

  /* MANDATORY: Automatically adapt native UI to user system preferences */
  color-scheme: light dark;

  /* Example inherited color property */
  accent-color: var(--accent-color);
}

pre, code {
  color-scheme: dark;

  /* **Mandatory**: any inherited color properties must be set again, even if to the same design tokens */
  accent-color: var(--accent-color);
}

پشتیبانی مرورگر و بازگشت‌ها برای مقادیر تصویر light-dark()‎

برای مرورگرهایی که از light-dark() برای تصاویر پشتیبانی نمی‌کنند، از image-set() به‌عنوان سوئیچ استفاده کنید: به هر گزینه یک type() از یک ویژگی سفارشی بدهید و گزینه غیرفعال را روی یک نوع MIME پشتیبانی‌نشده تنظیم کنید تا مرورگر آن گزینه را نادیده بگیرد. گزینه فعال مقدار خالی دریافت می‌کند، بنابراین گزینه image-set() ساده بدون type() است.

یک‌بار کلید را در :root تعریف کنید. سپس هر سایت استفاده فقط به هر دو تصویر به‌صورت درون‌خطی نیاز دارد، مانند light-dark().

:root {
  --light-type: ;
  --dark-type: type("image/do-not-use");

  /* MANDATORY: Fallback for browsers without light-dark() image support */
  @media (prefers-color-scheme: dark) {
    --light-type: type("image/do-not-use");
    --dark-type: ;
  }
}

.hero {
  background-image: image-set(url(hero-light.png) var(--light-type), url(hero-dark.png) var(--dark-type));

  @supports (background-image: light-dark(url("a"), url("b"))) {
    background-image: light-dark(url(hero-light.png), url(hero-dark.png));
  }
}
  • فقط تصویر انتخاب‌شده بارگیری می‌شود.
  • وضوح‌ها همچنان کار می‌کنند: image-set(url(a-1x.png) 1x var(--light-type), url(a-2x.png) 2x var(--light-type), url(b-1x.png) 1x var(--dark-type), url(b-2x.png) 2x var(--dark-type)).
  • از type("") برای گزینه فعال استفاده نکنید. مرورگرها رشته خالی را به‌عنوان پشتیبانی‌نشده درنظر می‌گیرند و همه گزینه‌ها را حذف می‌کنند.
  • برخلاف light-dark()، این کلید از color-scheme تنظیم‌شده در زیردرخت پیروی نمی‌کند. کلید روشن/خاموش دستی، یا هر زیردرختی که color-scheme را تنظیم می‌کند، باید --light-type و --dark-type را نیز تغییر دهد.

جایگزین: یک دارایی سفارشی برای هر تصویر

ساده‌تر است وقتی فقط چند تصویر متفاوت هستند، اما هر تصویر به شاخه پرس‌وجوی رسانه‌ای خودش نیاز دارد و یک کلید دستی باید هرکدام را تغییر دهد.

:root {
  --hero-image: url(hero-light.png);

  @media (prefers-color-scheme: dark) {
    --hero-image: url(hero-dark.png);
  }

  @supports (background-image: light-dark(url("a"), url("b"))) {
    --hero-image: light-dark(url(hero-light.png), url(hero-dark.png));
  }
}

.hero {
  background-image: var(--hero-image);
}

پشتیبانی مرورگر و جایگزین‌ها برای image()‎

از گرادیانی با یک توقف رنگ و بدون موقعیت استفاده کنید، مثلاً linear-gradient(blue).

برای پشتیبانی گسترده‌تر مرورگر، می‌توانید صریحاً 0 100% موقعیت برای توقف تک‌رنگ ارائه دهید، مثلاً linear-gradient(blue 0 100%).

پشتیبانی مرورگر و بازگشت برای scrollbar-color

این ویژگی ارتقای پیش‌رو است و همیشه به جایگزین نیاز ندارد.

اگر سبک‌بندی مهم است و هدف «خط پایه» کاربر «خط پایه به‌طور گسترده دردسترس» یا قدیمی‌تر است، باید شبه‌عناصر غیراستاندارد ::-webkit-scrollbar را به‌عنوان جایگزین اضافه کنید.

جایگزین‌های قدیمی را در یک بلوک @supports not (scrollbar-color: auto) قرار دهید تا از تداخل بین ویژگی‌های استاندارد و انتخاب‌کننده‌های قدیمی WebKit در مرورگرهایی که از هر دو به‌صورت بومی پشتیبانی می‌کنند، جلوگیری شود.

اگر از ویژگی‌های سفارشی برای تعریف رنگ‌ها استفاده می‌کنید، این ویژگی‌ها به‌طور خودکار به انتخاب‌کننده‌های قدیمی WebKit منتقل می‌شوند. لازم نیست آن‌ها را تکرار کنید.

/* Legacy fallback for WebKit/Blink browsers */
@supports not (scrollbar-color: auto) {
  .scroller::-webkit-scrollbar {
    /* Must define base size in WebKit for custom colors to be visual */
    width: 12px;
    height: 12px;
  }

  .scroller::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb);
  }

  .scroller::-webkit-scrollbar-track {
    background: var(--scrollbar-track);
  }
}

پشتیبانی مرورگر و جایگزین‌ها برای accent-color

خصوصیت accent-color ارتقای پیش‌رو است. مرورگرهایی که از این ویژگی پشتیبانی نمی‌کنند آن را نادیده می‌گیرند و از رنگ‌های واسط کاربر پیش‌فرض خود استفاده می‌کنند.