המאפיין color-scheme מציין באילו ערכות צבעים (כמו בהירה או כהה) הדף תומך. כך הדפדפן יודע שהוא יכול להחיל באופן אוטומטי עיצוב על רכיבים מקוריים בממשק המשתמש, כמו פסי גלילה, פקדי טפסים ורקע ברירת המחדל של אזור העריכה, כדי להתאים אותם לעיצוב של האתר ולצמצם את ההבזקים הלבנים במהלך הטעינה הראשונית.
הטמעה
1. הצהרה על סכימות נתמכות ב-HTML
חובה: כדי למנוע "הבזק של תוכן ללא עיצוב" (FOUC), צריך להוסיף תג <meta> ב-<head> כדי לוודא שהדפדפן יודע באילו עיצובים אתם תומכים עוד לפני שהוא מתחיל לעבד את התוכן. התג <meta> עוזר למנוע FOUC על ידי הגדרת צבע הקנבס הראשוני בשלב מוקדם, אבל יכול להיות שהוא לא ימנע לחלוטין הבזקים בכל הדפדפנים או בתנאי טעינה מסוימים.
<!-- MANDATORY: Declare support for both light and dark themes -->
<meta name="color-scheme" content="light dark">
2. החלת ערכת צבעים על כל הדף ב-CSS :root או ב-HTML
חובה: צריך להחיל את המאפיין color-scheme על הרכיב html או על המחלקה המדומה :root. דפדפנים בודקים באופן ספציפי את רכיב הבסיס כדי לקבוע את העיצוב של כל אזור התצוגה – כולל פסי הגלילה הבסיסיים והרקע הראשוני של ה-canvas. אם המדיניות מוחלת רק על 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;
}
3. הגדרת אסימוני צבע בהירים וכהים
אפשר להשתמש בפונקציה 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 כדי להגדיר זוגות צבעים שונים שמביאים בחשבון את הצבעים של הדפדפן ושל ממשק המשתמש של מערכת ההפעלה מסביב לדף (או של הדף שמסביב, כשהדף משמש כ-iframe).
לדוגמה, אפשר להשתמש בעיצוב בהיר קצת יותר עמום כשהגדרת המערכת היא dark, או בעיצוב כהה עם יותר ניגודיות כשהגדרת המערכת היא light, כדי שהדף לא ייראה חזק מדי מבחינה ויזואלית בהשוואה לממשק המשתמש שמסביב.
התאמה אישית מפורטת של ממשק המשתמש בדפדפן
ההגדרה color-scheme כבר מתאימה את ממשק המשתמש של הדפדפן לערכת הצבעים שבשימוש, אבל היא תשתמש בברירות המחדל של מערכת ההפעלה או בצבעי המערכת, שלא בהכרח יתאימו באופן מושלם לעיצוב של האתר.
דפדפנים מודרניים חושפים כמה נקודות עיגון (hooks) להתאמה אישית מפורטת של הרכיבים האלה.
אל תטמיעו מחדש פקדים מקוריים רק כדי להתאים אישית את המראה שלהם, בלי למצות את ה-hooks להתאמה אישית שדפדפנים מודרניים מספקים.
הגדרת הצבע המשני
בחלק מממשק המשתמש של הדפדפן (למשל, תיבות סימון מסומנות או פסי הזזה) נעשה שימוש בצבע משני.
כברירת מחדל, הצבע נקבע לפי הגדרת מערכת ההפעלה, אבל אפשר להשתמש במאפיין 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 משתמשת בפסי גלילה מקוריים מסוג overlay. כדי לאלץ את macOS לעבד צבעים בהתאמה אישית, חובה להתאים אותם ל-scrollbar-width(למשל,thinאוauto). - גם אם מחילים את
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() בכל אחד מהם כדי להחיל צבעים שמתאימים לערכת הצבעים שבשימוש.
4. תמונות שונות למצב בהיר ולמצב כהה
בתמונות CSS, אפשר להשתמש ב-light-dark() גם כדי לספק ערכי תמונות שונים.
חשוב: שני הערכים ב-light-dark() חייבים להיות מאותו סוג. אי אפשר לשלב צבע עם תמונה.
אם אחד משני הערכים חייב להיות תמונה, צריך להשתמש ב-image(<color>) כדי לעטוף את ערך הצבע.
זיהוי עיצוב מבוסס-JS
רוב ההסתעפויות של ערכת הצבעים צריכות להתבצע ב-CSS, שמתאים את עצמו אוטומטית לשינויים.
כל קוד JS שקורא את matchMedia("(prefers-color-scheme: dark)").matches חייב גם לטפל באירוע change שלו, כי העדפת המערכת יכולה להשתנות בכל שלב.
אופציונלי: הטמעת מתג לערכת צבעים
אם אתם רוצים לאפשר למשתמשים לשנות באופן ידני את ברירת המחדל של המערכת באתר הזה, אתם יכולים להטמיע מתג למצב כהה. ברוב האתרים אין צורך במתג קבוע בממשק המשתמש של האתר. בדרך כלל מספיק להגדיר את ערכת הצבעים של המערכת כברירת מחדל, ואפשר גם להוסיף הגדרה במשטח הגדרות נפרד. בקטע מתגים למצב כהה מפורטות שיטות מומלצות להטמעת מתג למצב כהה (קבוע או לא).
אופציונלי: שינויים ספציפיים לרכיבים
אפשר לשנות את העיצוב הגלובלי של רכיבים ספציפיים על ידי הגדרת color-scheme בהם.
מידע נוסף ודברים שחשוב לשים לב אליהם מפורטים במאמר עיצובים בהירים/כהים ספציפיים לרכיבים.
בעיות ידועות שחשוב לשים לב אליהן
בעיות שצריך לשים לב אליהן כשמשתמשים ב-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) ותעדו אותו עבור המטמיעים.
- אם אתם שולטים גם בהורה וגם ב-iframe: מעבירים את ערכת הצבעים של ההורה ל-iframe באופן מפורש – באמצעות פרמטר של כתובת URL (
אסטרטגיות חלופיות
תמיכה בדפדפנים וחלופות לערכת הצבעים
המאפיין 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);
}
ערכי ברירת מחדל ותמיכה בדפדפנים בערכי תמונות של 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
התכונה הזו היא שיפור הדרגתי (progressive enhancement) ולא תמיד נדרשים לה פתרונות חלופיים.
אם העיצוב חשוב והיעד של המשתמש ב-Baseline הוא "Baseline Widely Available" או גרסה קודמת, כדאי לכלול את הרכיבים המדומים הלא סטנדרטיים של ::-webkit-scrollbar כחלופות.
כדאי לעטוף את רכיבי ה-fallback מדור קודם בבלוק @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 הוא שיפור הדרגתי (progressive enhancement).
דפדפנים שלא תומכים במאפיין הזה יתעלמו ממנו וישתמשו בצבעי ברירת המחדל של ממשק המשתמש שלהם.