מתגים למצב כהה

מתג למצב כהה מאפשר למשתמשים לשנות את ערכת הצבעים של המערכת באתר אחד. כדי להחיל את השינוי, צריך לעדכן את <meta name="color-scheme">: light dark פירושו "לפי העדפות המערכת", light או dark מצמידים סכימה מפורשת. הצבעים (light-dark()), צבעי המערכת וממשק המשתמש המקורי מבוססים על המאפיין color-scheme של CSS, כך שהמתג פועל על ידי סנכרון המאפיין הזה עם <meta> (ראו שיקוף של שינוי ברירת המחדל ב-CSS).

מתג קבוע, שליטה בהגדרות או בלי מתג בכלל?

ברוב האתרים לא צריך מתג קבוע לערכת הצבעים בממשק המשתמש של האתר (כותרת עליונה, ניווט, כותרת תחתונה וכו'). כברירת מחדל, צריך לפעול לפי העדפות המערכת. אם נדרש שינוי ידני, צריך להציב את אמצעי הבקרה בממשק הגדרות נפרד: דף הגדרות, חלונית או שכבת-על.

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

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

הטמעה

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

מודל נתונים

מודל הנתונים של מתג המצב הכהה כולל בדרך כלל שלושה מצבים:

  1. מערכת (אין ערך שמור): ממשק המשתמש פועל לפי ערכת הצבעים של המערכת. רצוי שזו תהיה ברירת המחדל.
  2. בהיר (מאוחסן בתור "light"): ממשק המשתמש משתמש בעיצוב הבהיר, בלי קשר לערכת הצבעים של המערכת.
  3. כהה (מאוחסן בתור "dark"): ממשק המשתמש משתמש בעיצוב הכהה בלי קשר לערכת הצבעים של המערכת.

המצב הזה בדרך כלל מאוחסן ב-localStorage ומשתקף ברכיב <meta name="color-scheme"> בכותרת המסמך.

הצגת השינוי ב-CSS

התג <meta> הוא רק רמז לתצוגה: כל הצהרה של color-scheme ב-CSS של היוצר מבטלת אותו. מכיוון שמצב כהה מגדיר את color-scheme: light dark ב-:root, עדכון של <meta> בלבד הוא no-op – CSS מנצח. ממפים את <meta> בחזרה לנכס כדי שההיררכיה תפעל לפיו:

:root {
  color-scheme: light dark;

  &:has(> head > meta[name="color-scheme"][content="dark"]) {
    color-scheme: dark;
  }
  &:has(> head > meta[name="color-scheme"][content="light"]) {
    color-scheme: light;
  }
}

אל תכתבו בתוך הקוד את color-scheme: light או את color-scheme: dark כברירת המחדל ברמת הבסיס. ההצהרה הבסיסית חייבת להישאר light dark. ה-CSS לא יכול להיות תלוי ב-JS: אם ה-JS לא פועל אף פעם, ה-<meta> נשאר light dark והאתר פועל לפי העדפות המערכת – שום דבר לא משתבש.

שמירה על העדפות ומניעת FOUC (הבזק של תוכן לא מעוצב)

שומרים את השינוי ב-localStorage; מסירים את הרשומה כשחוזרים לברירת המחדל של המערכת.

כדי למנוע הבהוב של ערכת הצבעים הלא נכונה, צריך להחיל את הערך השמור בסקריפט מוטבע (לא type=module, לא defer) שמוצב מיד אחרי הרכיב <meta>:

<meta name="color-scheme" content="light dark">
<script>
document.querySelector('meta[name="color-scheme"]').content = localStorage.getItem("color-scheme") ?? "light dark";
</script>
  • הסקריפט הזה מוטמע רק כדי למנוע FOUC. הקפידו שהקובץ יהיה קטן ככל האפשר. אפשר לטעון בהמשך קובץ JS נוסף לטיפול בהחלפת ערכת הצבעים.
  • במקרים נדירים, הגישה ל-localStorage עלולה לגרום לשגיאה (למשל, נתוני האתר חסומים), אבל מכיוון שהסקריפט הזה לא עושה שום דבר אחר, תופעת הלוואי היחידה תהיה שגיאה במסוף. אם זה חשוב, צריך להוסיף את התג try .. catch. צריך לוודא שהעיצוב עדיין מוחל על הדף, גם אם אי אפשר לשמור אותו.
  • השינוי יכול להשתנות מכרטיסייה אחרת: צריך לטפל באירוע storage של window כדי להישאר בסנכרון.
  • אל תשתמשו ב-matchMedia() כדי להסיר את הערך השמור כשהעדפות המערכת משתנות בהתאם. מערכות ההפעלה של משתמשים רבים מחליפות ערכות צבעים באופן אוטומטי בהתאם לשעה ביום. אם הערך השמור יוסר בכל פעם ששני המצבים האלה יתרחשו בו-זמנית, לא תהיה אפשרות להצמיד ערכת צבעים בכלל.

הסתעפות לערכי HTML וערכים שאינם צבעים

לא צריך לעשות שום דבר נוסף עם הצבעים: אחרי שממפים את <meta> ל-color-scheme (למעלה), light-dark() פועל לפי השינוי. הקטע הזה עוסק בהתאמה של ערכים אחרים (למשל font-weight, מקורות מדיה וכו').

כשהדף פשוט פועל לפי העדפות המערכת, אפשר להשתמש ב-(prefers-color-scheme: dark) להסתעפות, כולל במקורות <picture> או <video>. כשעוקפים את ערכת הצבעים, נוצרת בעיה נוספת: העדפות המערכת כבר לא משמשות כמקור המידע המהימן, ואין חלופה ישירה לממשקי API שמקבלים רק שאילתות מדיה.

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

אפשר לשלב את שאילתת המדיה עם בורר :root:has(> head > meta[name="color-scheme"][content="dark"]) (או light) כדי להסתעף. בקטע שילובים של סלקטורים וכללי @‎ מוסבר איך להטמיע את זה בצורה אלגנטית.

גם האפשרויות של אמצעי הבקרה עצמו הן ענפים ללא צבע: צריך לכלול את שני המצבים בתגי העיצוב (סמל וטקסט פעולה שמוסתר באופן חזותי, למשל "מעבר לעיצוב כהה") ולהסתיר את המצב הלא פעיל באמצעות הבוררים האלה. ‫display: none גם מסיר את האפשרות המיותרת מה-AT, כך שהפקד לא צריך JS כדי להישאר עדכני כשהעדפות המערכת משתנות.

במדיה בתוך HTML, הדרך היחידה כרגע היא לכלול את שתי הגרסאות כרכיבים נפרדים ולהחליף את החשיפה בהתאם. הסתרת רכיבי <source> באמצעות display: none לא פועלת.

ממשק משתמש

שתיים או שלוש מדינות?

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

עדיף להציג שני מצבים במתגים שמוצגים במקומות שבהם המקום מוגבל, כמו מתגים קבועים בכרום של האתר (כותרת עליונה, ניווט, כותרת תחתונה וכו'), שבהם המקום מוגבל ושינוי ההגדרות בדרך כלל לא קשור למטרה של המשתמש.

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

שלושה מצבים מפורשים מוצדקים גם אם האתר מיישם סכמות שמותאמות להקשר (למשל, מצב בהיר עמום יותר כשהמערכת במצב כהה), כי אז יש הבדל אמיתי בין "בהיר" לבין "מערכת (כרגע בהיר)".

מתגים דו-מצביים

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

שני המצבים היחידים צריכים להיות:

  1. ברירת המחדל של המערכת – אין ערך שמור, תוכן <meta> light dark. מוצג בתור הערך הנוכחי שהתקבל בהתאמת הנתונים (לדוגמה, סמל של שמש כשהמצב בהיר).
  2. שינוי – מאוחסן באופן מילולי בתור light או dark.

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

כשהמשתמש מפעיל או משבית את האפשרות:

  1. ערכת העיצוב המטורגטת = ההפך מערכת העיצוב שמוצגת כרגע (הערך השמור, אם יש כזה, אחרת העדפת המערכת). כוונת המשתמש היא "לבחור את ההפך ממה שמוצג כרגע", ולא "לבחור את ההפך מברירת המחדל של המערכת".
  2. אם היעד שונה מהעדפת המערכת הנוכחית, צריך לאחסן אותו באופן מילולי.
  3. אם היעד תואם להעדפת המערכת הנוכחית, המשתמש מבטל את השינוי: מסירים את הערך השמור. אל תשמרו אותו – זה יצמיד את הסכימה באופן בלתי נראה לשינויים עתידיים במערכת.
  4. מגדירים את התוכן של <meta> לערך השמור, או ל-light dark אם אין ערך שמור.

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

תרחיש לדוגמה, שמתחיל כשהמערכת מוגדרת למצב בהיר:

  1. המשתמש מפעיל או משבית את המתג. העיצוב הכהה שונה מהעדפת המערכת, ולכן הערך dark נשמר והאתר עובר לעיצוב כהה.
  2. הגדרת מערכת ההפעלה משתנה למצב כהה. האתר נשאר כהה (הערך השמור תואם עכשיו להעדפת המערכת, אבל הוא נשמר).
  3. הגדרת מערכת ההפעלה משתנה חזרה למצב בהיר. האתר נשאר כהה.
  4. המשתמש מפעיל או משבית את המתג. היעד (בהיר) תואם להעדפת המערכת, ולכן הערך המאוחסן מוסר והאתר פועל שוב לפי המערכת.

מתגים עם שלושה מצבים

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

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

  • סמל, למשל סמל של שמש בפינה השמאלית התחתונה של סמל המערכת
  • טקסט, למשל "מערכת (כרגע בהיר)"