prefers-color-scheme: Hello darkness, my old friend

تبلیغات اغراق‌آمیز یا ضرورت؟ همه چیز را درباره حالت تاریک و نحوه پشتیبانی از آن به‌نفع کاربران خود بیاموزید!

مقدمه

حالت تاریک قبل‌از حالت تاریک

رایانه‌ای قدیمی مربوط به قبل‌از دهه ۹۰ که نوشتار سبز را روی پس‌زمینه سیاه نشان می‌دهد.
پرده سبز (منبع)

با حالت تاریک، دایره را کامل کرده‌ایم. در آغاز عصر رایانش شخصی، حالت تاریک موضوعی اختیاری نبود، بلکه یک واقعیت بود: نمایشگرهای رایانه تک‌رنگ CRT با شلیک پرتوهای الکترونی روی صفحه‌نمایش فسفرسانس کار می‌کردند و فسفر استفاده‌شده در CRTهای اولیه سبز بود. چون نوشتار به رنگ سبز نمایش داده می‌شد و بقیه صفحه سیاه بود، این مدل‌ها اغلب صفحه سبز نامیده می‌شدند.

نمایشگری که نسخه Windows 3.1 از Microsoft Word را نشان می‌دهد.
تیره روی سفید (منبع)

لامپ‌های پرتو کاتدی رنگی که بعداً معرفی شدند، بااستفاده از فسفرهای قرمز، سبز، و آبی، رنگ‌های متعددی را نمایش می‌دادند. آن‌ها با فعال کردن هم‌زمان هر سه فسفر، رنگ سفید را ایجاد کردند. با ظهور WYSIWYG پیچیده‌تر نشر رومیزی، ایده شبیه کردن سند مجازی به یک ورق کاغذ فیزیکی محبوب شد.

مجموعه‌ای از پنجره‌ها که صفحه‌های وب تیره روی سفید را در مرورگر اولیه WorldWideWeb نشان می‌دهد.
مرورگر WorldWideWeb (منبع)

اینجا بود که تیره روی سفید به‌عنوان یک گرایش طراحی آغاز شد، و این گرایش به وب مبتنی بر سند اولیه منتقل شد. اولین مرورگر، WorldWideWeb (به‌خاطر داشته باشید که CSS هنوز اختراع نشده بود)، صفحه‌های وب را به این شکل نمایش می‌داد. نکته جالب: دومین مرورگر تاریخ، Line Mode Browser—یک مرورگر مبتنی بر پایانه— سبز روی زمینه تیره بود. این روزها، صفحه‌های وب و برنامه‌های وب معمولاً با نوشتار تیره روی پس‌زمینه روشن طراحی می‌شوند، فرضیه پایه‌ای که در برگه سبک نگارش نماینده کاربر، ازجمله Chrome، نیز به‌صورت کد ثابت نوشته شده است.

استفاده از تلفن همراه در رختخواب

دوران CRTها مدت‌ها است که به‌سر آمده است. مصرف و تولید محتوا به دستگاه‌های همراه منتقل شده است که از صفحه‌نمایش‌های LCD با نور پس‌زمینه یا AMOLED کم‌مصرف استفاده می‌کنند. رایانه‌ها، رایانه‌های لوحی، و تلفن‌های هوشمند کوچک‌تر و قابل‌حمل‌تر منجر به الگوهای استفاده جدیدی شدند. کارهای تفریحی مثل مرور وب، کدنویسی برای سرگرمی، و بازی‌های پیشرفته اغلب بعداز ساعات کاری در محیط‌های کم‌نور انجام می‌شوند. افراد حتی شب‌ها در رختخواب از دستگاه‌هایشان لذت می‌برند. هرچه افراد بیشتری در تاریکی از دستگاه‌هایشان استفاده می‌کنند، ایده بازگشت به ریشه‌های روشن روی تیره محبوب‌تر می‌شود.

چرا حالت تاریک

حالت تاریک به‌دلایل زیبایی‌شناختی

وقتی از افراد پرسیده می‌شود چرا حالت تیره را دوست دارند یا می‌خواهند، محبوب‌ترین پاسخ این است که «برای چشم‌ها راحت‌تر است» و پاسخ بعدی این است که «شیک و زیبا است». Apple در مستندات توسعه‌دهنده «حالت تاریک» خود به‌صراحت می‌نویسد: «انتخاب فعال کردن ظاهر روشن یا تیره برای اکثر کاربران یک انتخاب زیبایی‌شناختی است و ممکن است به شرایط نور محیط مربوط نباشد.»

CloseView در Mac OS System 7 با حالت «سفید روی سیاه» (منبع)

حالت تاریک به‌عنوان ابزار دسترس‌پذیری

همچنین افرادی هستند که واقعاً به حالت تاریک نیاز دارند و از آن به‌عنوان ابزار دسترس‌پذیری دیگری استفاده می‌کنند، برای مثال، کاربران کم‌بینا. اولین باری که چنین ابزار دسترس‌پذیری‌ای را دیدم، ویژگی CloseView در System 7 بود که دکمه‌ای برای جابه‌جایی بین سیاه روی سفید و سفید روی سیاه داشت. درحالی‌که System 7 از رنگ پشتیبانی می‌کرد، میانای کاربر پیش‌فرض همچنان سیاه‌وسفید بود.

این پیاده‌سازی‌های مبتنی بر وارونگی، با معرفی رنگ، نقاط ضعف خود را نشان دادند. پژوهش کاربر توسط Szpiro و همکاران درباره نحوه دسترسی افراد کم‌بینا به دستگاه‌های رایانه‌ای نشان داد که همه کاربران مصاحبه‌شده از تصاویر وارونه‌شده خوششان نمی‌آمد، اما بسیاری از آن‌ها نوشتار روشن در پس‌زمینه تیره را ترجیح می‌دادند. Apple این اولویت کاربر را با ویژگی‌ای به‌نام وارون‌سازی هوشمند برآورده می‌کند، که رنگ‌های نمایشگر را معکوس می‌کند، به‌جز تصاویر، رسانه‌ها، و برخی‌از برنامه‌هایی که از سبک‌های رنگ تیره استفاده می‌کنند.

یک شکل خاص از کم‌بینایی، «سندروم بینایی رایانه‌ای» است که با نام «خستگی چشم دیجیتال» نیز شناخته می‌شود و تعریف آن عبارت است از «ترکیبی از مشکلات چشم و بینایی مرتبط با استفاده از رایانه (ازجمله رایانه رومیزی، رایانه کیفی، و رایانه لوحی) و سایر نمایشگرهای الکترونیکی (مانند تلفن‌های هوشمند و دستگاه‌های کتاب‌خوان الکترونیکی).» پیشنهاد شده است که استفاده از دستگاه‌های الکترونیکی توسط نوجوانان، به‌ویژه در شب، منجر به افزایش خطر کوتاه‌تر شدن مدت خواب، طولانی‌تر شدن تأخیر شروع خواب، و افزایش کمبود خواب می‌شود. علاوه‌براین، به‌طور گسترده گزارش شده است که قرار گرفتن در معرض نور آبی در تنظیم ریتم شبانه‌روزی و چرخه خواب نقش دارد، و محیط‌های نوری نامنظم ممکن است منجر به محرومیت از خواب شود، که طبق تحقیقات روزنفیلد احتمالاً بر خلق‌وخو و عملکرد وظایف تأثیر می‌گذارد. برای محدود کردن این اثرات منفی، کاهش نور آبی با تنظیم دمای رنگ نمایشگر ازطریق ویژگی‌هایی مانند Night Shift در iOS یا نور شب در Android می‌تواند کمک کند، همچنین اجتناب از نورهای روشن یا نورهای نامنظم به‌طور کلی ازطریق زمینه‌های تیره یا حالت‌های تیره.

صرفه‌جویی در مصرف باتری با حالت تیره در صفحه‌نمایش‌های AMOLED

درنهایت، حالت تیره به‌دلیل صرفه‌جویی زیاد در مصرف انرژی در صفحه‌نمایش‌های AMOLED شناخته شده است. مطالعات موردی Android که بر برنامه‌های محبوب Google مثل YouTube تمرکز داشتند نشان داده‌اند که صرفه‌جویی در مصرف برق می‌تواند تا ۶۰٪ باشد. ویدیو زیر جزئیات بیشتری درباره این مطالعات موردی و میزان صرفه‌جویی در مصرف برق به‌ازای هر برنامه ارائه می‌دهد.

فعال کردن حالت تاریک در سیستم‌عامل

اکنون که پیشینه اینکه چرا حالت تاریک برای بسیاری از کاربران بسیار مهم است را پوشش دادم، بیایید بررسی کنیم که چگونه می‌توانید از آن پشتیبانی کنید.

تنظیمات حالت تاریک Android Q

سیستم‌عامل‌هایی که از حالت تاریک یا زمینه تیره پشتیبانی می‌کنند معمولاً گزینه‌ای برای فعال کردن آن در جایی از تنظیمات دارند. در macOS X، این تنظیم در بخش General (عمومی) اولویت‌های سیستم قرار دارد و Appearance (ظاهر) (نماگرفت) نامیده می‌شود، و در Windows 10، در بخش Colors (رنگ‌ها) قرار دارد و Choose your color (انتخاب رنگ) (نماگرفت) نامیده می‌شود. در Android Q، می‌توانید آن را در بخش نمایشگر به‌عنوان کلید دوحالته زمینه تیره (نماگرفت) پیدا کنید، و در iOS 13، می‌توانید ظاهر را در بخش نمایشگر و روشنایی تنظیمات (نماگرفت) تغییر دهید.

پُرسمان رسانه prefers-color-scheme

یک بخش تئوری دیگر قبل‌از اینکه شروع کنم. پرس‌وجوهای رسانه به نویسندگان اجازه می‌دهد مقادیر یا ویژگی‌های نماینده کاربر یا دستگاه نمایش را، مستقل از سند درحال رندر شدن، آزمایش و پرس‌وجو کنند. از آن‌ها در قانون CSS @media برای اعمال مشروط سبک‌ها به سند، و در زمینه‌ها و زبان‌های مختلف دیگر، مانند HTML و جاوا اسکریپت، استفاده می‌شود. Media Queries Level 5 ویژگی‌های رسانه‌ای ترجیحات کاربر را معرفی می‌کند، یعنی روشی برای سایت‌ها تا روش ترجیحی کاربر برای نمایش محتوا را شناسایی کنند.

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

  • light: نشان می‌دهد که کاربر به سیستم اطلاع داده است که صفحه‌ای با زمینه روشن را ترجیح می‌دهد (نوشتار تیره روی پس‌زمینه روشن).
  • dark: نشان می‌دهد که کاربر به سیستم اطلاع داده است که صفحه‌ای با زمینه تیره را ترجیح می‌دهد (نوشتار روشن روی پس‌زمینه تیره).

پشتیبانی از حالت تاریک

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

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

if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
  console.log('🎉 Dark mode is supported');
}

در زمان نوشتن این سند، prefers-color-scheme هم در رایانه و هم در تلفن همراه (درصورت دردسترس بودن) توسط Chrome و Edge از نسخه ۷۶، Firefox از نسخه ۶۷، و Safari از نسخه ۱۲.۱ در macOS و از نسخه ۱۳ در iOS پشتیبانی می‌شود. برای همه مرورگرهای دیگر، می‌توانید سند Can I use support tables را بررسی کنید.

یادگیری درباره اولویت‌های کاربر در زمان درخواست

سرصفحه اشاره کارخواه Sec-CH-Prefers-Color-Scheme به سایت‌ها اجازه می‌دهد تا درصورت تمایل، اولویت‌های طرح رنگ کاربر را در زمان درخواست دریافت کنند، و به سرورها اجازه می‌دهد تا CSS مناسب را به‌صورت درون‌خطی قرار دهند و درنتیجه از نمایش سریع طرح رنگ نادرست جلوگیری کنند.

حالت تاریک در عمل

درنهایت، بیایید ببینیم پشتیبانی از حالت تاریک در عمل چگونه است. درست مثل Highlander، با حالت تیره فقط یک حالت می‌تواند وجود داشته باشد: تیره یا روشن، اما هرگز هر دو باهم! چرا این را می‌گویم؟ زیرا این واقعیت باید بر استراتژی بارگذاری تأثیر بگذارد. لطفاً کاربران را مجبور نکنید CSS را در مسیر پردازش بحرانی که برای حالتی است که درحال‌حاضر استفاده نمی‌کنند بارگیری کنند. بنابراین برای بهینه‌سازی سرعت بار کردن، CSS را برای برنامه نمونه که توصیه‌های زیر را در عمل نشان می‌دهد به سه بخش تقسیم کرده‌ام تا CSS غیربحرانی را به‌تعویق بیندازم:

  • style.css که حاوی قوانین عمومی است که به‌طور جهانی در سایت استفاده می‌شود.
  • dark.css که فقط حاوی قوانین موردنیاز برای حالت تاریک است.
  • light.css که فقط حاوی قوانین موردنیاز برای حالت روشن است.

درحال بار کردن استراتژی

دو مورد آخر، light.css و dark.css، به‌صورت شرطی با پُرسمان <link media> بار می‌شوند. در ابتدا، همه مرورگرها از prefers-color-scheme پشتیبانی نمی‌کنند (بااستفاده از الگوی بالا قابل‌تشخیص است)، که من با بار کردن فایل پیش‌فرض light.css ازطریق عنصر <link rel="stylesheet"> درج‌شده به‌صورت شرطی در یک اسکریپت درون‌خطی کوچک به‌صورت پویا با آن برخورد می‌کنم (روشن یک انتخاب اختیاری است، می‌توانستم تیره را هم به‌عنوان تجربه بازگشت پیش‌فرض انتخاب کنم). برای جلوگیری از فلش محتوای بدون سبک، محتوای صفحه را تا زمانی که light.css بارگیری شود پنهان می‌کنم.

<script>
  // If `prefers-color-scheme` is not supported, fall back to light mode.
  // In this case, light.css will be downloaded with `highest` priority.
  if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') {
    document.documentElement.style.display = 'none';
    document.head.insertAdjacentHTML(
      'beforeend',
      '<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = \'\'">',
    );
  }
</script>
<!--
  Conditionally either load the light or the dark stylesheet. The matching file
  will be downloaded with `highest`, the non-matching file with `lowest`
  priority. If the browser doesn't support `prefers-color-scheme`, the media
  query is unknown and the files are downloaded with `lowest` priority (but
  above I already force `highest` priority for my default light experience).
-->
<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)" />
<link
  rel="stylesheet"
  href="/light.css"
  media="(prefers-color-scheme: light)"
/>
<!-- The main stylesheet -->
<link rel="stylesheet" href="/style.css" />

معماری برگه سبک نگارش

من از متغیرهای CSS حداکثر استفاده را می‌کنم، این کار به style.css عمومی من اجازه می‌دهد که، خب، عمومی باشد، و همه سفارشی‌سازی‌های حالت روشن یا تاریک در دو فایل دیگر dark.css و light.css اتفاق می‌افتد. در زیر می‌توانید گزیده‌ای از سبک‌های واقعی را ببینید، اما همین گزیده برای انتقال ایده کلی کافی است. دو متغیر -⁠-⁠color و -⁠-⁠background-color را تعریف می‌کنم که اساساً یک طرح زمینه پایه تیره روی روشن و روشن روی تیره ایجاد می‌کنند.

/* light.css: 👉 dark-on-light */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
}
/* dark.css: 👉 light-on-dark */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
}

سپس در style.css، از این متغیرها در قانون body { … } استفاده می‌کنم. چون آن‌ها در :root کلاس کاذب CSS تعریف شده‌اند—یک انتخاب‌گر که در HTML نشان‌دهنده عنصر <html> است و با انتخاب‌گر html یکسان است، به‌جز اینکه ویژگی آن بالاتر است—آن‌ها به‌صورت آبشاری پایین می‌آیند، که برای اعلام متغیرهای CSS سراسری به من کمک می‌کند.

/* style.css */
:root {
  color-scheme: light dark;
}

body {
  color: var(--color);
  background-color: var(--background-color);
}

در نمونه کد بالا، احتمالاً متوجه ویژگی color-scheme با مقدار جداشده با فاصله light dark شده‌اید.

این به مرورگر می‌گوید که برنامه من از کدام زمینه‌های رنگی پشتیبانی می‌کند و به آن اجازه می‌دهد تا انواع خاصی از برگه سبک نگارش نماینده کاربر را فعال کند، که برای مثال، به مرورگر اجازه می‌دهد فیلدهای فرم را با پس‌زمینه تیره و نوشتار روشن ارائه دهد، نوارهای پیمایش را تنظیم کند، یا رنگ برجسته‌سازی حساس به زمینه را فعال کند. جزئیات دقیق color-scheme در CSS Color Adjustment Module Level 1 مشخص شده است.

Everything else is then just a matter of defining CSS variables for things that matter on my site. سازمان‌دهی معنایی سبک‌ها هنگام کار با حالت تاریک بسیار کمک می‌کند. برای مثال، به‌جای -⁠-⁠highlight-yellow، متغیر را -⁠-⁠accent-color بنامید، زیرا «زرد» ممکن است در حالت تاریک واقعاً زرد نباشد یا برعکس. در زیر نمونه‌ای از چند متغیر دیگر که در مثال خودم استفاده می‌کنم آورده شده است.

/* dark.css */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
  --link-color: rgb(0, 188, 212);
  --main-headline-color: rgb(233, 30, 99);
  --accent-background-color: rgb(0, 188, 212);
  --accent-color: rgb(5, 5, 5);
}
/* light.css */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
  --link-color: rgb(0, 0, 238);
  --main-headline-color: rgb(0, 0, 192);
  --accent-background-color: rgb(0, 0, 238);
  --accent-color: rgb(250, 250, 250);
}

نمونه کامل

در نمونه نمایشی جاسازی‌شده زیر، می‌توانید نمونه کامل‌شده‌ای را ببینید که مفاهیم بالا را در عمل نشان می‌دهد. حالت تاریک را در تنظیمات سیستم‌عامل خاص خودتان روشن و خاموش کنید و ببینید صفحه چگونه واکنش نشان می‌دهد.

درحال بار کردن تأثیر

وقتی با این مثال بازی می‌کنید، می‌توانید ببینید چرا dark.css و light.css را ازطریق پرسمان‌های رسانه بار می‌کنم. حالت تاریک را روشن و خاموش کنید و صفحه را مجدداً بار کنید: برگه‌های سبک نگارش خاصی که درحال‌حاضر مطابقت ندارند همچنان بار می‌شوند، اما با کمترین اولویت، به‌طوری‌که هرگز با منابعی که سایت درحال‌حاضر به آن‌ها نیاز دارد رقابت نمی‌کنند.

نمودار بارگیری شبکه که نشان می‌دهد چگونه در حالت روشن، CSS حالت تاریک با کمترین اولویت بارگیری می‌شود.
سایت در حالت روشن، CSS حالت تاریک را با کمترین اولویت بار می‌کند.
نمودار بارگیری شبکه که نشان می‌دهد چگونه در حالت تاریک، CSS حالت روشن با کمترین اولویت بارگیری می‌شود.
سایت در حالت تاریک، CSS حالت روشن را با کمترین اولویت بار می‌کند.
نمودار بارگیری شبکه نشان می‌دهد که چگونه در حالت روشن پیش‌فرض، CSS حالت تاریک با کمترین اولویت بارگیری می‌شود.
سایت در حالت روشن پیش‌فرض در مرورگری که از prefers-color-scheme پشتیبانی نمی‌کند، CSS حالت تاریک را با کمترین اولویت بار می‌کند.

واکنش به تغییرات حالت تاریک

مانند هر تغییر پرسمان رسانه دیگری، تغییرات حالت تاریک را می‌توان ازطریق جاوا اسکریپت مشترک شد. می‌توانید از این برای تغییر پویای نماد وب‌سایت یک صفحه یا تغییر <meta name="theme-color"> که رنگ نوار نشانی وب را در Chrome تعیین می‌کند استفاده کنید. نمونه کامل بالا این موضوع را در عمل نشان می‌دهد، برای دیدن تغییرات رنگ زمینه و نماد وب‌سایت، نسخه نمایشی را در برگه جداگانه‌ای باز کنید.

const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
darkModeMediaQuery.addEventListener('change', (e) => {
  const darkModeOn = e.matches;
  console.log(`Dark mode is ${darkModeOn ? '🌒 on' : '☀️ off'}.`);
});

از Chromium 93 و Safari 15، می‌توانید رنگ را براساس پُرسمان رسانه با مشخصه media عنصر رنگ زمینه meta تنظیم کنید. اولین موردی که مطابقت داشته باشد انتخاب می‌شود. برای مثال، می‌توانید یک رنگ برای حالت روشن و رنگ دیگری برای حالت تاریک داشته باشید. در زمان نوشتن، نمی‌توانید آن‌ها را در مانیفست خود تعریف کنید. مشکل GitHub w3c/manifest#975 را ببینید.

<meta
  name="theme-color"
  media="(prefers-color-scheme: light)"
  content="white"
/>
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />

اشکال‌زدایی و آزمایش حالت تاریک

شبیه‌سازی prefers-color-scheme در DevTools

تغییر دادن رنگ‌بندی کل سیستم‌عامل می‌تواند خیلی سریع آزاردهنده شود، بنابراین Chrome DevTools اکنون به شما امکان می‌دهد رنگ‌بندی ترجیحی کاربر را به‌گونه‌ای شبیه‌سازی کنید که فقط بر برگه قابل‌مشاهده فعلی تأثیر بگذارد. منوی فرمان را باز کنید، شروع به تایپ کردن Rendering کنید، فرمان Show Rendering را اجرا کنید، و سپس گزینه شبیه‌سازی ویژگی رسانه CSS‏ prefers-color-scheme را تغییر دهید.

نماگرفتی از گزینه «Emulate CSS media feature prefers-color-scheme» که در برگه «پرداخت» در Chrome DevTools قرار دارد.

گرفتن نماگرفت از prefers-color-scheme با Puppeteer

Puppeteer کتابخانه Node.js است که میانای برنامه‌سازی کاربردی سطح بالایی برای کنترل Chrome یا Chromium ازطریق پروتکل DevTools ارائه می‌دهد. با dark-mode-screenshot، یک اسکریپت Puppeteer ارائه می‌دهیم که به شما امکان می‌دهد از صفحه‌هایتان در هر دو حالت تاریک و روشن نماگرفت ایجاد کنید. می‌توانید این اسکریپت را به‌صورت یک‌باره اجرا کنید، یا آن را بخشی از مجموعه آزمون «ادغام مداوم» (CI) خود قرار دهید.

npx dark-mode-screenshot --url https://googlechromelabs.github.io/dark-mode-toggle/demo/ --output screenshot --fullPage --pause 750

روال‌های مطلوب حالت تیره

از سفید خالص استفاده نکنید

جزئیات کوچکی که ممکن است متوجه شده باشید این است که من از سفید خالص استفاده نمی‌کنم. درعوض، برای جلوگیری از درخشش و پخش شدن در محتوای تیره اطراف، سفید کمی تیره‌تری را انتخاب می‌کنم. چیزی مثل rgb(250, 250, 250) خوب کار می‌کند.

رنگی کردن مجدد و تیره کردن تصاویر عکاسی

اگر دو نماگرفت زیر را باهم مقایسه کنید، متوجه خواهید شد که نه‌تنها زمینه اصلی از تیره روی روشن به روشن روی تیره تغییر کرده است، بلکه نگاره اصلی نیز کمی متفاوت به‌نظر می‌رسد. پژوهش کاربر من نشان داده است که اکثر افراد نظرسنجی‌شده تصاویری را ترجیح می‌دهند که وقتی حالت تاریک فعال است، کمی کمتر زنده و درخشان باشند. من به این کار رنگ‌آمیزی مجدد می‌گویم.

نگاره اصلی در حالت تاریک کمی تیره شده است.
نگاره اصلی معمولی در حالت روشن.

رنگ‌آمیزی مجدد را می‌توان ازطریق فیلتر CSS روی تصاویر من انجام داد. من از انتخابگر CSS استفاده می‌کنم که با همه تصاویری که .svg در نشانی وب خود ندارند مطابقت دارد، ایده این است که می‌توانم به گرافیک‌های برداری (نمادها) رنگ‌آمیزی مجدد متفاوتی نسبت به تصاویرم (عکس‌ها) بدهم، اطلاعات بیشتر درباره این موضوع در پاراگراف بعدی آمده است. توجه کنید که چگونه دوباره از متغیر CSS استفاده می‌کنم، تا بتوانم بعداً فیلترم را به‌طور انعطاف‌پذیر تغییر دهم.

ازآنجایی‌که رنگ‌آمیزی مجدد فقط در حالت تاریک لازم است، یعنی وقتی dark.css فعال است، قوانین متناظری در light.css وجود ندارد.

/* dark.css */
--image-filter: grayscale(50%);

img:not([src*='.svg']) {
  filter: var(--image-filter);
}

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

همه افراد یکسان نیستند و نیازهای متفاوتی به حالت تاریک دارند. با پایبندی به روش رنگ‌آمیزی مجدد که در بالا شرح داده شد، می‌توانم به‌راحتی شدت مقیاس خاکستری را به اولویت کاربر تبدیل کنم که می‌توانم آن را ازطریق جاوا اسکریپت تغییر دهم، و با تنظیم مقدار 0%، می‌توانم رنگ‌آمیزی مجدد را نیز به‌طور کامل غیرفعال کنم. توجه داشته باشید که document.documentElement مرجعی به عنصر ریشه سند ارائه می‌دهد، یعنی همان عنصری که می‌توانم با :root کلاس کاذب CSS به آن ارجاع دهم.

const filter = 'grayscale(70%)';
document.documentElement.style.setProperty('--image-filter', value);

وارونه کردن گرافیک‌های برداری و نمادها

برای گرافیک‌های برداری—که در مورد من به‌عنوان نمادهایی استفاده می‌شوند که ازطریق عناصر <img> به آن‌ها ارجاع می‌دهم—از روش رنگ‌آمیزی مجدد متفاوتی استفاده می‌کنم. هرچند پژوهش‌ها نشان داده است که افراد وارونگی را برای عکس‌ها دوست ندارند، این ویژگی برای اکثر نمادها بسیار خوب کار می‌کند. دوباره از متغیرهای CSS برای تعیین مقدار وارونگی در حالت عادی و در حالت :hover استفاده می‌کنم.

نمادها و نوشتار سفید روی پس‌زمینه سیاه.
نمادها در حالت تاریک وارونه می‌شوند.
نمادها و نوشتار سیاه روی پس‌زمینه سفید.
نمادهای معمولی در حالت روشن.

توجه کنید که چگونه دوباره نمادها را فقط در dark.css معکوس می‌کنم اما در light.css نه، و چگونه :hover در دو حالت شدت معکوس‌سازی متفاوتی دریافت می‌کند تا نماد کمی تیره‌تر یا کمی روشن‌تر به‌نظر برسد، بسته به حالتی که کاربر انتخاب کرده است.

/* dark.css */
--icon-filter: invert(100%);
--icon-filter_hover: invert(40%);

img[src*='.svg'] {
  filter: var(--icon-filter);
}
/* light.css */
--icon-filter_hover: invert(60%);
/* style.css */
img[src*='.svg']:hover {
  filter: var(--icon-filter_hover);
}

استفاده از currentColor برای SVGهای درون‌خطی

برای تصاویر SVG درون‌خطی، به‌جای استفاده از فیلترهای وارونگی، می‌توانید از کلیدواژه CSS currentColor استفاده کنید که نشان‌دهنده مقدار ویژگی color عنصر است. این کار به شما امکان می‌دهد از مقدار color در دارایی‌هایی استفاده کنید که به‌طور پیش‌فرض آن را دریافت نمی‌کنند. به‌طور مناسب، اگر از currentColor به‌عنوان مقدار مشخصه‌های fill یا stroke SVG استفاده شود، درعوض مقدارش را از مقدار موروثی خصوصیت رنگ می‌گیرد. حتی بهتر: این ویژگی برای <svg><use href="…"></svg> هم کار می‌کند، بنابراین می‌توانید منابع جداگانه‌ای داشته باشید و currentColor همچنان در بافت اعمال خواهد شد. لطفاً توجه داشته باشید که این فقط برای SVGهای درون‌خطی یا <use href="…"> کار می‌کند، اما برای SVGهایی که به‌عنوان src تصویر یا به‌نحوی ازطریق CSS ارجاع داده شده‌اند کار نمی‌کند. می‌توانید این مورد را در نسخه نمایشی زیر ببینید.

<!-- Some inline SVG -->
<svg xmlns="http://www.w3.org/2000/svg"
    stroke="currentColor"
>
  […]
</svg>

گذار روان بین حالت‌ها

جابه‌جایی از حالت تاریک به حالت روشن یا برعکس می‌تواند به‌لطف این واقعیت که هم color و هم background-color ویژگی‌های CSS پویانمایی‌پذیر هستند، روان‌تر انجام شود. ساختن پویانمایی به آسانی اعلام دو transition برای دو ویژگی است. مثال زیر ایده کلی را نشان می‌دهد، می‌توانید آن را به‌صورت زنده در نسخه نمایشی تجربه کنید.

body {
  --duration: 0.5s;
  --timing: ease;

  color: var(--color);
  background-color: var(--background-color);

  transition: color var(--duration) var(--timing), background-color var(
        --duration
      ) var(--timing);
}

جهت هنری با حالت تاریک

While for loading performance reasons in general I recommend to exclusively work with prefers-color-scheme in the media attribute of <link> elements (rather than inline in stylesheets), there are situations where you actually may want to work with prefers-color-scheme directly inline in your HTML code. کارگردانی هنری یکی از این موقعیت‌ها است. در وب، کارگردانی هنری به ظاهر بصری کلی صفحه و نحوه برقراری ارتباط بصری آن، تحریک حالات، تضاد ویژگی‌ها، و جذابیت روان‌شناختی برای مخاطب هدف می‌پردازد.

در حالت تیره، تصمیم‌گیری درباره اینکه بهترین تصویر در یک حالت خاص چیست و اینکه آیا رنگ‌آمیزی مجدد تصاویر شاید به‌اندازه کافی خوب نیست، به قضاوت طراح بستگی دارد. اگر با عنصر <picture> استفاده شود، <source> تصویری که باید نشان داده شود می‌تواند به مشخصه media وابسته شود. در مثال زیر، نیم‌کره غربی را برای حالت تاریک و نیم‌کره شرقی را برای حالت روشن نشان می‌دهم یا وقتی اولویتی ارائه نشده باشد، در همه موارد دیگر به‌طور پیش‌فرض نیم‌کره شرقی را نشان می‌دهم. البته این صرفاً برای اهداف نمایشی است. برای دیدن تفاوت، «حالت تاریک» را در دستگاهتان روشن/خاموش کنید.

<picture>
  <source srcset="western.webp" media="(prefers-color-scheme: dark)" />
  <source srcset="eastern.webp" media="(prefers-color-scheme: light)" />
  <img src="eastern.webp" />
</picture>

حالت تاریک، اما با امکان انصراف

همان‌طور که در بخش چرا حالت تاریک در بالا ذکر شد، حالت تاریک برای اکثر کاربران یک انتخاب زیبایی‌شناختی است. درنتیجه، برخی‌از کاربران ممکن است درواقع بخواهند واسط کاربر سیستم‌عاملشان تیره باشد، اما همچنان ترجیح دهند صفحه‌های وب را همان‌طور که عادت دارند ببینند. الگوی عالی این است که در ابتدا به سیگنالی که مرورگر ازطریق prefers-color-scheme ارسال می‌کند پایبند باشید، اما سپس به‌صورت اختیاری به کاربران اجازه دهید تنظیمات سطح سیستم خود را لغو کنند.

عنصر سفارشی <dark-mode-toggle>

البته می‌توانید خودتان کد این کار را ایجاد کنید، اما می‌توانید از عنصر سفارشی آماده (مؤلفه وب) که من دقیقاً برای این منظور ایجاد کرده‌ام نیز استفاده کنید. نام آن <dark-mode-toggle> است و یک کلید (حالت تیره: روشن/خاموش) یا یک تغییردهنده زمینه (زمینه: روشن/تیره) به صفحه‌تان اضافه می‌کند که می‌توانید آن را کاملاً سفارشی‌سازی کنید. نسخه نمایشی زیر عنصر را در عمل نشان می‌دهد (اوه، و من همچنین 🤫 بی‌صدا آن را در همه دیگر نمونه‌های بالا گنجانده‌ام).

<dark-mode-toggle
  legend="Theme Switcher"
  appearance="switch"
  dark="Dark"
  light="Light"
  remember="Remember this"
></dark-mode-toggle>
<dark-mode-toggle> در حالت روشن.
<dark-mode-toggle> در حالت تاریک.

در نسخه نمایشی زیر، روی کنترل‌های حالت تاریک در گوشه بالا کلیک کنید یا تک‌ضرب بزنید. اگر چارگوش انتخاب را در کنترل سوم و چهارم علامت بزنید، ببینید که چگونه انتخاب حالت شما حتی وقتی صفحه را مجدداً بار می‌کنید به‌خاطر سپرده می‌شود. این کار به بازدیدکنندگان شما اجازه می‌دهد سیستم‌عامل خود را در حالت تاریک نگه دارند، اما از سایت شما در حالت روشن لذت ببرند یا برعکس.

نتیجه‌گیری‌ها

کار کردن با حالت تاریک و پشتیبانی از آن جالب است و مسیرهای طراحی جدیدی را باز می‌کند. برای برخی‌از بازدیدکنندگان شما، این می‌تواند تفاوت بین عدم توانایی در مدیریت سایت شما و تبدیل شدن به یک کاربر راضی باشد. برخی مشکلات وجود دارد و آزمایش دقیق قطعاً لازم است، اما حالت تاریک قطعاً فرصتی عالی برای شما است تا نشان دهید که به همه کاربران خود اهمیت می‌دهید. روال‌های مطلوب ذکرشده در این پست و کمک‌کننده‌هایی مانند <dark-mode-toggle> عنصر سفارشی باید شما را در توانایی‌تان برای ایجاد یک تجربه شگفت‌انگیز از حالت تاریک مطمئن کند. در Twitter به من اطلاع دهید که چه چیزی ایجاد می‌کنید و آیا این پست مفید بود یا نه، یا پیشنهادهایی برای بهبود آن ارائه دهید. از اینکه خواندید سپاس‌گزاریم! 🌒

منابع برای پُرسمان رسانه prefers-color-scheme:

منابع مربوط به متا تگ color-scheme و ویژگی CSS:

پیوندهای عمومی حالت تاریک:

مقاله‌های پژوهشی پس‌زمینه برای این پست:

تصدیق‌نامه‌ها

ویژگی رسانه prefers-color-scheme، دارایی CSS color-scheme، و متا تگ مربوطه حاصل کار پیاده‌سازی 👏 Rune Lillesveen است. رون همچنین یکی از ویراستاران مشخصات CSS Color Adjustment Module Level 1 است. می‌خواهم از لوکاس زبیلوت، روان مروود، چیراگ دسای، و راب دادسون برای بررسی‌های دقیقشان از این مقاله تشکر کنم. استراتژی بارگیری ایده جیک آرچیبالد است. Emilio Cobos Álvarez روش تشخیص prefers-color-scheme صحیح را به من نشان داده است. نکته با SVGهای ارجاع‌شده و currentColor از تیموتی هچر گرفته شده است. درنهایت، از شرکت‌کنندگان ناشناس متعددی که در مطالعات کاربر مختلف شرکت کردند و به شکل‌گیری توصیه‌های این مقاله کمک کردند سپاس‌گزارم.