עיצובים בהירים או כהים ספציפיים לרכיבים

תכונות אינטרנט: color-scheme light-dark()‎

בדרך כלל מגדירים את המאפיין color-scheme ברמה הבסיסית (root), אבל אפשר להגדיר אותו גם ברכיבים ספציפיים כדי לאלץ אותם להשתמש בערכת צבעים שונה משאר הדף. האפשרות הזו יכולה להיות שימושית לרכיבים שצריך תמיד להציג בערכת צבעים ספציפית (למשל, תמיד במצב כהה או בהיר).

תרחישים לדוגמה:

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

מתי לשנות צבעים ומתי לאלץ את color-scheme?

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

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

כששוקלים להשתמש ב-color-scheme אחר ברכיב, כדאי לשאול את עצמכם:

  • האם ממשק המשתמש המובנה של הדפדפן שלא הותאם אישית (למשל, פקדי טפסים, פסי גלילה וכו') צריך להשתמש בערכת הצבעים הזו או להתאים את עצמו לערכת הצבעים של הדף? -> אם מדובר באפשרות הראשונה, אל תשתמשו ב-color-scheme.
  • האם צבעי light-dark() צריכים להופיע כמו בשאר הדף או לפי השינוי? -> אם מדובר באפשרות הראשונה, אל תשתמשו ב-color-scheme.
  • האם הצאצאים צריכים להיות בcolor-scheme הזה? אם לא, אל תשתמשו ב-color-scheme.

הטמעה בסיסית

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

אחרי שמגדירים color-scheme ברמת הדף ומשתמשים באסימוני צבע שמושפעים ממנו (למשל באמצעות light-dark()), אפשר פשוט להגדיר color-scheme ברכיבים ספציפיים כדי לשנות את מצב הצבע של עץ המשנה הזה:

pre, code, .dark {
  color-scheme: dark;
}

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

התאמת ערכים שאינם צבעים

‫light-dark() פועל כרגע רק עם צבעים.

שיטות מומלצות

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

בעיות ידועות שחשוב לשים לב אליהן

נקודה חשובה: ירושה של צבעי light-dark()

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

בין היתר, אסור:

  • מאפייני צבע מובנים שעוברים בירושה, כמו color,‏ accent-color,‏ fill,‏ stroke,‏ text-shadow,‏ caret-color
  • כל המאפיינים המותאמים אישית הרשומים שניתנים להעברה בירושה עם syntax: <color> ו-inherits: true
  • כל נכס אחר מסוג <color> שהוגדר כ-inherit

זה אומר שאתם צריכים:

  • לא לרשום מאפיינים מותאמים אישית שמיועדים להכיל טוקנים של עיצוב (למשל --surface-color) בתור <color>. האסימונים צריכים לשמור על הביטוי light-dark() שלהם Express Live כדי שצאצאים יוכלו לפתור אותם מחדש תחת color-scheme אחר.
  • כשמגדירים את color-scheme ברכיב, צריך לציין מחדש את כל המאפיינים של <color> שעברו בירושה, שאולי הוגדרו לערכים של light-dark() (באופן ישיר או באמצעות אסימוני עיצוב), גם אם מדובר באותו אסימון עיצוב.
  • לא להשתמש ב-inherit במאפיינים של <color> ברכיבים עם שינוי של color-scheme (אפשר להשתמש בצאצאים שלהם).
  • כן כדאי להשתמש במאפייני <color> רשומים בתרחיש השימוש ההפוך: כשרוצים במכוון ליצור תמונת מצב של הצבע שנקבע לאב הקדמון ולמנוע ממנו להיקבע מחדש ב-color-scheme של הצאצא. לדוגמה, צילום הרקע של הדף כדי להשתמש בו במקום אחר.
  • אם אתם צריכים להוסיף אנימציה לצבע, השתמשו במאפיין נפרד שרשום ב-@property<color> ברכיב שמוסיפים לו אנימציה (נדרש רישום לאינטרפולציה של צבעים) – זה לא אסימון עיצוב, אלא יעד אנימציה לכל רכיב, כך שאין התנגשות עם הכלל שלמעלה.

דוגמה:

:root {
    --accent-color: light-dark(blue, skyblue);
    --surface-color: light-dark(white, #222);
    --text-color: light-dark(#111, white);

    color-scheme: light dark;
    accent-color: var(--accent-color);
    color: var(--text-color);
}

body {
    /* --surface-color dynamically switches despite being inherited because --surface-color is not registered */
    background: var(--surface-color);
}

pre, code {
    color-scheme: dark;
    background: var(--surface-color);

    /* Without this, accent-color would be blue, not skyblue! */
    accent-color: var(--accent-color);

    /* Without this, text-color would be #111, not white! */
    color: var(--text-color);
}

בעיות שצריך לשים לב אליהן כשמשתמשים ב-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, מגדירים מחלקה ב-<html> (או ב-color-scheme ב-:root) מהאות הזה במקום להסתמך על prefers-color-scheme.
    • אם אתם שולטים רק בדף המוטמע: אין דרך אמינה לזהות את ה-color-scheme של ההקשר המוטמע מתוך ה-iframe ב-Safari. חשפו פרמטר עיצוב מפורש ב-API להטמעה (למשל, מחרוזת שאילתה או פרוטוקול postMessage) ותעדו אותו עבור המטמיעים.

אסטרטגיות חלופיות

תמיכה בדפדפנים וחלופות לערכת הצבעים

המאפיין color-scheme הוא שיפור הדרגתי (progressive enhancement). דפדפנים שלא תומכים במצב כהה יתעלמו מהמאפיין הזה וישתמשו בממשק המשתמש שמוגדר כברירת מחדל במצב בהיר.

כדי להתאים את האתר להעדפות של המשתמש בדפדפנים ישנים יותר, אפשר להשתמש בשאילתות מדיה של 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);
}