העדפת ערכת צבעים: שלום חושך, חבר שלי

הייפ מוגזם או צורך אמיתי? כאן תוכלו לקרוא את כל מה שצריך לדעת על מצב כהה ואיך לתמוך בו לטובת המשתמשים שלכם.

מבוא

מצב כהה לפני מצב כהה

מחשב ישן מלפני שנות ה-90 עם טקסט ירוק על רקע שחור.
מסך ירוק (מקור)

השלמנו את המעבר למצב כהה. בתחילת הדרך של המחשוב האישי, המצב הכהה לא היה עניין של בחירה, אלא עובדה: מסכי מחשב CRT מונוכרומטיים פעלו על ידי ירי של קרני אלקטרונים על מסך זרחני, והזרחן ששימש במסכי CRT מוקדמים היה ירוק. מכיוון שהטקסט הוצג בירוק ושאר המסך היה שחור, הדגמים האלה כונו לעיתים קרובות מסכים ירוקים.

מסך שמוצגת בו גרסת Windows 3.1 של Microsoft Word.
כהה על גבי לבן (מקור)

במסכי CRT צבעוניים שהוצגו לאחר מכן, הוצגו כמה צבעים באמצעות זרחן אדום, ירוק וכחול. כדי ליצור צבע לבן, הם הפעילו את כל שלושת הזרחנים בו-זמנית. עם הופעתן של תוכנות WYSIWYG מתוחכמות יותר להוצאה לאור שולחנית, הרעיון של יצירת מסמך וירטואלי שדומה לדף נייר פיזי הפך לפופולרי.

אשכול של חלונות שבהם מוצגים דפי אינטרנט כהים על רקע לבן בדפדפן WorldWideWeb המוקדם.
דפדפן WorldWideWeb (מקור)

כאן התחילה מגמת העיצוב של כהה על גבי לבן, והמגמה הזו המשיכה גם באינטרנט המוקדם שהתבסס על מסמכים. הדפדפן הראשון, WorldWideWeb (זוכרים, CSS עוד לא הומצא), הציג דפי אינטרנט בצורה הזו. עובדה מעניינת: הדפדפן השני שנוצר אי פעם, Line Mode Browser – דפדפן מבוסס-טרמינל – היה ירוק על רקע כהה. בימינו, דפי אינטרנט ואפליקציות אינטרנט בדרך כלל מעוצבים עם טקסט כהה על רקע בהיר, הנחת יסוד שגם מקודדת בגיליונות הסגנונות של סוכני המשתמשים, כולל של Chrome.

טלפון נייד בשימוש במיטה

הימים של מסכי CRT חלפו מזמן. הצריכה והיצירה של תוכן עברו למכשירים ניידים עם מסכי LCD עם תאורה אחורית או מסכי AMOLED חסכוניים באנרגיה. מחשבים, טאבלטים וסמארטפונים קטנים וניידים יותר הובילו לדפוסי שימוש חדשים. משימות פנאי כמו גלישה בדפדפן אינטרנט, תכנות בשביל הכיף ומשחקים מתקדמים מתרחשות לעיתים קרובות אחרי שעות העבודה בסביבות חשוכות. אנשים נהנים מהמכשירים שלהם אפילו במיטה בלילה. ככל שיותר אנשים משתמשים במכשירים שלהם בחושך, כך הרעיון של חזרה למקורות של טקסט בהיר על רקע כהה הופך לפופולרי יותר.

למה כדאי להשתמש במצב כהה

מצב כהה מסיבות אסתטיות

כששואלים אנשים למה הם אוהבים או רוצים מצב כהה, התשובה הכי נפוצה היא "זה יותר נעים לעיניים", ואחריה "זה אלגנטי ויפה". במאמרי העזרה למפתחים בנושא מצב כהה של אפל כתוב במפורש: "הבחירה אם להפעיל עיצוב בהיר או כהה היא בחירה אסתטית עבור רוב המשתמשים, ויכול להיות שהיא לא קשורה לתנאי התאורה בסביבה".

CloseView ב-Mac OS System 7 עם מצב "לבן על שחור" (מקור)

מצב כהה ככלי נגישות

יש גם אנשים שבאמת צריכים את המצב הכהה ומשתמשים בו ככלי נגישות נוסף, למשל משתמשים עם לקות ראייה. המופע המוקדם ביותר של כלי נגישות כזה שמצאתי הוא התכונה CloseView של System 7, שכללה מתג לשחור על לבן וללבן על שחור. למרות שמערכת System 7 תמכה בצבע, ממשק המשתמש שמוגדר כברירת מחדל עדיין היה בשחור-לבן.

ההטמעות האלה, שמבוססות על היפוך, הראו את החולשות שלהן ברגע שהוצג צבע. מחקר על התנהגות משתמשים שערכו Szpiro ואחרים בנושא איך אנשים עם לקות ראייה ניגשים למכשירי מחשוב הראה שכל המשתמשים שהשתתפו בראיונות לא אהבו תמונות הפוכות, אבל רבים מהם העדיפו טקסט בהיר על רקע כהה. אפל נותנת מענה להעדפה הזו של המשתמשים באמצעות תכונה שנקראת היפוך חכם. התכונה הזו הופכת את הצבעים בתצוגה, חוץ מאשר בתמונות, במדיה ובאפליקציות מסוימות שמשתמשות בסגנונות של צבעים כהים.

סוג מיוחד של ראייה לקויה הוא תסמונת ראיית מחשב, שנקראת גם מאמץ עיניים דיגיטלי, ומוגדרת בתור "השילוב של בעיות עיניים וראייה שקשורות לשימוש במחשבים (כולל מחשבים נייחים, מחשבים ניידים וטאבלטים) ובמסכים אלקטרוניים אחרים (למשל סמארטפונים וקוראים אלקטרוניים)". הועלתה השערה שהשימוש במכשירים אלקטרוניים על ידי בני נוער, במיוחד בשעות הלילה, מוביל לסיכון מוגבר למשך שינה קצר יותר, זמן ארוך יותר עד להירדמות ומחסור מוגבר בשינה. בנוסף, דווח בהרחבה שחשיפה לאור כחול קשורה לוויסות של הקצב היממה ומחזור השינה, וסביבות תאורה לא סדירות עלולות להוביל למחסור בשינה, מה שעשוי להשפיע על מצב הרוח ועל הביצועים במשימות, לפי מחקר של רוזנפילד. כדי להפחית את ההשפעות השליליות האלה, אפשר להפחית את האור הכחול על ידי שינוי טמפרטורת הצבע של המסך באמצעות תכונות כמו Night Shift ב-iOS או תאורת לילה ב-Android. אפשר גם להימנע מאורות בהירים או לא סדירים באופן כללי באמצעות עיצובים כהים או מצבים כהים.

חיסכון בחשמל במצב כהה במסכי AMOLED

בנוסף, ידוע שהעיצוב הכהה חוסך הרבה אנרגיה במסכי AMOLED. במקרי בוחן של Android שהתמקדו באפליקציות פופולריות של Google כמו YouTube, נמצא שהחיסכון בצריכת החשמל יכול להגיע עד ל-60%. בסרטון הבא יש פרטים נוספים על המקרים האלה לדוגמה ועל החיסכון בחשמל לכל אפליקציה.

הפעלת המצב הכהה במערכת ההפעלה

עכשיו, אחרי שהסברתי למה המצב הכהה כל כך חשוב להרבה משתמשים, בואו נראה איך אתם יכולים לתמוך בו.

הגדרות של מצב כהה ב-Android Q

במערכות הפעלה שתומכות במצב כהה או בעיצוב כהה, בדרך כלל יש אפשרות להפעיל אותו בהגדרות. ב-macOS X, ההגדרה נמצאת בקטע General (כללי) בהעדפות המערכת ונקראת Appearance (מראה) (צילום מסך). ב-Windows 10, ההגדרה נמצאת בקטע Colors (צבעים) ונקראת Choose your color (בחירת הצבע) (צילום מסך). ב-Android Q, אפשר למצוא את האפשרות הזו בקטע תצוגה כמתג להפעלה או השבתה של עיצוב כהה (צילום מסך). ב-iOS 13, אפשר לשנות את המראה בקטע תצוגה ובהירות בהגדרות (צילום מסך).

שאילתת המדיה prefers-color-scheme

עוד תיאוריה אחת לפני שנתחיל. שאילתות מדיה מאפשרות ליוצרים לבדוק ולשאול ערכים או תכונות של סוכן המשתמש או מכשיר התצוגה, ללא קשר למסמך שעובר עיבוד. משתמשים בהן בכלל ה-CSS @media כדי להחיל סגנונות על מסמך באופן מותנה, ובהקשרים ובשפות אחרות, כמו HTML ו-JavaScript. ב-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 החל מגרסה 76, ב-Firefox החל מגרסה 67, ב-Safari החל מגרסה 12.1 ב-macOS והחל מגרסה 13 ב-iOS. לגבי כל הדפדפנים האחרים, אפשר לעיין במסמך Can I use support tables.

למידה על העדפות המשתמש בזמן הבקשה

הכותרת Sec-CH-Prefers-Color-Scheme של איסוף אותות בצד הלקוח מאפשרת לאתרים לקבל את ההעדפות של המשתמש לגבי ערכת הצבעים בזמן הבקשה, וכך השרתים יכולים להטמיע את ה-CSS הנכון ולהימנע מהבהוב של ערכת צבעים שגויה.

מצב כהה בפועל

עכשיו נראה איך תמיכה במצב כהה נראית בפועל. כמו בסרט איש הנצח, במצב כהה יכול להיות רק אחד: כהה או בהיר, אבל אף פעם לא שניהם! למה אני מזכיר את זה? כי העובדה הזו אמורה להשפיע על אסטרטגיית הטעינה. אל תאלצו את המשתמשים להוריד 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 { … }. הם מוגדרים במחלקה המדומה (pseudo-class) של CSS‏ :root – סלקטור שמייצג ב-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.

כל השאר הוא רק עניין של הגדרת משתני CSS לדברים שחשובים באתר שלי. ארגון סגנונות לפי משמעות עוזר מאוד כשעובדים עם מצב כהה. לדוגמה, במקום -⁠-⁠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 של המצב הכהה בעדיפות הנמוכה ביותר.

תגובה לשינויים במצב הכהה

כמו כל שינוי אחר בשאילתת מדיה, אפשר להירשם לשינויים במצב כהה באמצעות JavaScript. אפשר להשתמש בזה, למשל, כדי לשנות באופן דינמי את סמל האתר של דף או לשנות את <meta name="theme-color"> שקובע את הצבע של סרגל כתובות ה-URL ב-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

<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 בכלי הפיתוח

החלפת ערכת הצבעים של כל מערכת ההפעלה יכולה להיות מעצבנת מאוד, ולכן כלי הפיתוח ל-Chrome מאפשרים עכשיו לדמות את ערכת הצבעים המועדפת על המשתמש באופן שמשפיע רק על הכרטיסייה שגלויה כרגע. פותחים את תפריט הפקודות, מתחילים להקליד Rendering, מריצים את הפקודה Show Rendering ואז משנים את האפשרות הדמיה של תכונת המדיה של CSS עם העדפה לערכת צבעים.

צילום מסך של האפשרות &quot;הדמיה של תכונת המדיה של CSS עם העדפה לערכת צבעים&quot; שנמצאת בכרטיסייה &quot;רינדור&quot; בכלי הפיתוח ל-Chrome.

צילום מסך של prefers-color-scheme באמצעות Puppeteer

‫Puppeteer היא ספריית Node.js שמספקת ממשק API ברמה גבוהה לשליטה ב-Chrome או ב-Chromium באמצעות פרוטוקול כלי הפיתוח. ב-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) יכול להתאים.

צביעה מחדש והכהיה של תמונות מצולמות

אם תשוו בין שני צילומי המסך שלמטה, תראו שלא רק העיצוב הראשי השתנה מכהה על בהיר לבהיר על כהה, אלא גם שהתמונה הראשית נראית קצת אחרת. המחקר שלי על התנהגות משתמשים הראה שרוב האנשים שהשתתפו בסקר מעדיפים תמונות קצת פחות בהירות וצבעוניות כשהעיצוב הכהה מופעל. אני קורא לזה צביעה מחדש.

התמונה הראשית (Hero) מוכהה מעט במצב כהה.
תמונה ראשית רגילה במצב בהיר.

אפשר לשנות את הצבעים באמצעות מסנן CSS בתמונות. אני משתמש בסלקטור ב-CSS שתואם לכל התמונות שאין להן .svg בכתובת ה-URL שלהן, כדי שאוכל לתת לפרטי גרפי וקטורי (סמלים) טיפול שונה של שינוי צבע מאשר לתמונות (תצלומים). מידע נוסף על כך מופיע בפסקה הבאה. שימו לב ששוב השתמשתי במשתנה CSS, כדי שאוכל לשנות את המסנן בצורה גמישה בהמשך.

מכיוון שצריך לשנות את הצבעים רק במצב כהה, כלומר כש-dark.css פעיל, אין כללים תואמים ב-light.css.

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

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

התאמה אישית של עוצמות הצביעה מחדש במצב כהה באמצעות JavaScript

לא כולם אותו דבר, ולאנשים שונים יש צרכים שונים לגבי המצב הכהה. אם נצמד לשיטת הצביעה מחדש שמתוארת למעלה, נוכל להפוך בקלות את עוצמת גווני האפור להעדפת משתמש שאפשר לשנות באמצעות JavaScript, ואם נגדיר ערך של 0%, נוכל גם להשבית לחלוטין את הצביעה מחדש. שימו לב ש-document.documentElement מספק הפניה לרכיב הבסיס של המסמך, כלומר לאותו רכיב שאפשר להפנות אליו באמצעות מחלקה מדומה של CSS‏ :root.

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 מוטבעות, במקום להשתמש במסנני היפוך, אתם יכולים להשתמש במילת המפתח currentColor ב-CSS שמייצגת את הערך של המאפיין 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);
}

ניהול אומנותי במצב כהה

מסיבות שקשורות לביצועי הטעינה, בדרך כלל מומלץ לעבוד רק עם prefers-color-scheme במאפיין media של רכיבי <link> (ולא בתוך השורה בגיליונות סגנונות). עם זאת, יש מצבים שבהם כדאי לעבוד עם prefers-color-scheme ישירות בתוך השורה בקוד ה-HTML. ניהול אומנותי הוא מצב כזה. באינטרנט, ניהול אומנותי עוסק במראה החזותי הכולל של דף ובאופן שבו הוא מתקשר מבחינה חזותית, מעורר מצבי רוח, יוצר ניגודיות בין תכונות ופונה מבחינה פסיכולוגית לקהל יעד.

במצב כהה, המעצב צריך להחליט מהי התמונה הטובה ביותר במצב מסוים, ואם צביעה מחדש של תמונות היא אולי לא מספיק טובה. אם משתמשים ברכיב <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> יעזרו לכם ליצור חוויית מצב כהה מדהימה. אשמח לשמוע ב-X מה יצרתם, אם הפוסט הזה עזר לכם ואם יש לכם הצעות לשיפור. תודה על שקראת מידע זה! 🌒

משאבים לשאילתת המדיה prefers-color-scheme:

מקורות מידע על המטא תג color-scheme ומאפיין ה-CSS:

קישורים כלליים למצב כהה:

מאמרי מחקר ברקע של הפוסט הזה:

תודות

תכונת המדיה prefers-color-scheme, מאפיין ה-CSS‏ color-scheme ומטא התג הקשור הם תוצאה של עבודת ההטמעה של 👏 Rune Lillesveen. רונה הוא גם עורך שותף של המפרט CSS Color Adjustment Module Level 1. אני רוצה 🙏 להודות ל-Lukasz Zbylut, ל-Rowan Merewood, ל-Chirag Desai, ול-Rob Dodson על הביקורות המקיפות שלהם על המאמר הזה. אסטרטגיית הטעינה היא פרי מוחו של ג'ייק ארצ'יבלד. אמיליו קובוס אלברז הפנה אותי לשיטת הזיהוי הנכונה של prefers-color-scheme. הטיפ עם קובצי ה-SVG וה-currentColor המקושרים הגיע מ-Timothy Hatcher. ולבסוף, אני רוצה להודות למשתתפים האנונימיים הרבים במחקרי המשתמשים השונים שעזרו לגבש את ההמלצות במאמר הזה.