בניית ערכת צבעים

סקירה כללית בסיסית על הגדרת ערכת צבעים דינמית וניתנת להתאמה אישית

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

דמו

אם אתם מעדיפים סרטון, הנה גרסה של הפוסט הזה ב-YouTube:

סקירה כללית

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

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

המותג

לרוב, צבע המותג כבר הוגדר והוא מועבר כhex או כrgb. צבע המותג הבסיסי של האתגר הזה לממשק משתמש הוא #0af. קודם כול, במערכת הצבעים הזו צריך להמיר את הערך ההקסדצימלי ל-hsl.

* {
  --brand: #0af;
  --brand: hsl(200 100% 50%);
}

כדי לאפשר את האפשרות להכהות או להאיר את צבע המותג, למשל ב-20%, צריך לחלץ את 3 הערוצים של ערך הצבע ב-HSL למאפיינים מותאמים אישית משלהם, כך:

* {
  --brand-hue: 200;
  --brand-saturation: 100%;
  --brand-lightness: 50%;
}

ב-CSS אפשר לבצע פעולות מתמטיות על מאפייני הצבע האלה, לדוגמה calc(var(--brand-lightness) - 20%) כדי להקטין את ערך הבהירות ב-20%. זהו הבסיס ליצירת ערכת צבעים, כי באמצעות CSS אפשר לשמור על כל הצבעים באותה משפחת גוונים על ידי שינוי רמות הרוויה והבהירות של ערכת הצבעים ב-HSL.

עיצוב בהיר

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

תצוגה מקדימה של תוצאות הסיום של העיצוב הבהיר

מותג

מתחילים בצבע המותג, ובונים אותו מחדש על ידי עטיפה של המאפיינים המותאמים אישית --brand-hue, ‏ --brand-saturation ו---brand-lightness בסוגריים של פונקציית hsl (), בלי חישובים:

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}

צבעי הטקסט

השלב הבא הוא בחירת צבעי הטקסט שיהיו חלק מערכת הצבעים. בעיצוב בהיר, הטקסט צריך להיות כהה מאוד. שימו לב שהבהירות של הצבעים הבאים נמוכה, הרבה מתחת ל-50%.

* {
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
}

--text1-light, מכיוון שהוא כהה מאוד ב-10% בהירות, הוא שומר על רמת הרוויה הגבוהה של 100%, כך שצבע המותג עדיין יכול להציץ דרך הכחול הצבאי הכהה.

--text2-light, הוא לא כהה כמו הצבע הראשון, וזה טוב כי הוא צבע משני, וגם הוא פחות רווי.

צבעי המשטח

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

* {
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
}

יצרנו 4 צבעים של משטחים כי לצבעים דקורטיביים בדרך כלל יש צורך בעוד וריאנטים, לרגעים אינטראקטיביים כמו :focus או :hover או כדי ליצור מראה של שכבות נייר. בתרחישים האלה, מומלץ להעביר את --surface2-light במצב של עכבר מרחף ל---surface3-light, כך שהעכבר מרחף גורם לעלייה בניגודיות (בהירות של 99% ל-92% בהירות, כלומר כהה יותר).

אזורים כהים

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

* {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

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

צבעים בהירים ביחד

אין צורך לחפש איך כל אחד מהצבעים הבהירים נוצר, הם כולם נמצאים במקום אחד ב-CSS.

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
  --surface-shadow-light: var(--brand-hue) 10% calc(var(--brand-lightness) / 5);
  --shadow-strength-light: .02;
}
צילום מסך של כל הצבעים הבהירים ביחד
Sandbox ב-CodePen

עיצוב כהה

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

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

תצוגה מקדימה של התוצאה הסופית של העיצוב הכהה

מותג

בעיצוב הבהיר נעשה שימוש ב-3 הערכים של ערוצי הצבעים ב-HSL של המותג ללא שינוי, לעומת העיצוב הכהה. רמת הרוויה מופחתת בחצי ורמת הבהירות מופחתת ב-50%.

* {
  --brand-dark: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 2)
    calc(var(--brand-lightness) / 1.5)
  );
}

צבעי הטקסט

בעיצוב כהה, צבעי הטקסט צריכים להיות בהירים. לצבעים הבאים יש ערכים גבוהים של בהירות, ולכן הם קרובים יותר ללבן.

* {
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
}

צבעי המשטח

בעיצוב כהה, צבעי השטח צריכים להיות כהים. לצבעים הבאים יש רמת בהירות ורוויה נמוכות, כאשר פני השטח הראשון הוא הכי כהה עם 10%.

* {
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
}

אזורים כהים

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

* {
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}

בנוסף, כדאי לבדוק את רמת הרוויה בצל. האם הצבע מופיע בממשק? כדאי לנסות להסיר את הרוויה מ-devtools, מה מעדיף?

צבעים כהים ביחד

* {
  --brand-dark: hsl(var(--brand-hue) calc(var(--brand-saturation) / 2) calc(var(--brand-lightness) / 1.5));
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}
צילום מסך של כל הצבעים הכהים ביחד
Sandbox ב-CodePen

עיצוב עמום

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

תצוגה מקדימה של התוצאות הסופיות מהעיצוב עם האורות מעומעמים

מותג

* {
  --brand-dim: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 1.25)
    calc(var(--brand-lightness) / 1.25)
  );
}

צבעי הטקסט

* {
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
}

צבעי המשטח

* {
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
}

אזורים כהים

* {
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}

עמעום כל הצבעים

* {
  --brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25));
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}
צילום מסך של הצבעים המוחשכים כולם ביחד
Sandbox ב-CodePen

צבעים נגישים

שימו לב שהבהירות הנמוכה ביותר בקבוצת צבעי הטקסט כהים היא 65%, והבהירות הגבוהה ביותר בפלטפורמות כהות היא 25%. כלומר, 40% מהבהירות היא מרחב נשימה בין הצבעים. בעיצוב הבהיר, יש 55% מרווח נשימה. אם ההבדלים בין רמת הבהירות של הטקסט לבין רמת הבהירות של פני השטח יהיו בטווח של 40-50%, זה יעזור לשמור על יחסים גבוהים של ניגודיות צבעים, וגם יעזור לכם לבצע התאמות עדינות במקרה שהציונים נמוכים.

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

מקישים על Shift + חץ למטה כדי להפחית את הבהירות ולהגדיל את הניגודיות עד שמגיעים ל

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

.surface1 {
  background-color: var(--surface1);
  color: var(--text2);
}

.surface2 {
  background-color: var(--surface2);
  color: var(--text2);
}

.surface3 {
  background-color: var(--surface3);
  color: var(--text1);
}

.surface4 {
  background-color: var(--surface4);
  color: var(--text1);
}
צילום מסך של שילובים של משטח עמום וטקסט
צילום מסך של שילובי הטקסט והמשטח המוארך באמצעות VisBug

Rad Shadow

העיצובים משתמשים במחלקת שירות שנקראת .rad-shadow. הצל הזה נוצר באמצעות הכלי Smooth Shadow, שאותו אני מאוד מעריך. לקחתי את קטע הקוד שנוצר והתאמתי אותו אישית עם הצבעים והחישובים של האטימות שלי. הסיבה לכך היא רציתי ליצור צללית שאוכל לשנות בכל ערכת צבעים.

כל צל לצד השני

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

:root {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

.rad-shadow {
  box-shadow:
    0 2.8px 2.2px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 6.7px 5.3px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .01)),
    0 12.5px 10px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 22.3px 17.9px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 41.8px 33.4px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 100px 80px hsl(var(--surface-shadow) / var(--shadow-strength))
  ;
}

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

שימוש בערכות הצבעים

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

כדי לעשות זאת, צריך להשתמש בסכמת הצבעים אך ורק דרך המאפיינים המותאמים אישית הכלליים, שנתאר בהמשך. כך, אנשים שמשתמשים במשתני העיצוב לא צריכים לדאוג לגבי ערכת הצבעים שמוגדרת כרגע, אלא רק להשתמש בצבעים של המשטח והטקסט. במקום color: var(--text1-light), צריך להשתמש ב-color: var(--text1). כל ההתאמות והשינויים של הצבעים מתבצעים ברמה גבוהה יותר ב-CSS.

בהמשך, סגנונות החיבור של העיצוב הבהיר בקוד הבא מקשרים בין מאפיין מותאם אישית גנרי לבין הצבע הספציפי של העיצוב הבהיר. מעכשיו, בכל השימוש ב-var(--brand) ייעשה שימוש בצבע הבהיר של המותג.

עיצוב בהיר (אוטומטי)

:root {
  color-scheme: light;
  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

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

עיצוב כהה (אוטומטי)

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --brand: var(--brand-dark);
    --text1: var(--text1-dark);
    --text2: var(--text2-dark);
    --surface1: var(--surface1-dark);
    --surface2: var(--surface2-dark);
    --surface3: var(--surface3-dark);
    --surface4: var(--surface4-dark);
    --surface-shadow: var(--surface-shadow-dark);
    --shadow-strength: var(--shadow-strength-dark);
  }
}

עיצוב בהיר

[color-scheme="light"] {
  color-scheme: light;

  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

עיצוב כהה

[color-scheme="dark"] {
  color-scheme: dark;

  --brand: var(--brand-dark);
  --text1: var(--text1-dark);
  --text2: var(--text2-dark);
  --surface1: var(--surface1-dark);
  --surface2: var(--surface2-dark);
  --surface3: var(--surface3-dark);
  --surface4: var(--surface4-dark);
  --surface-shadow: var(--surface-shadow-dark);
  --shadow-strength: var(--shadow-strength-dark);
}

עיצוב עמום

[color-scheme="dim"] {
  color-scheme: dark;

  --brand: var(--brand-dim);
  --text1: var(--text1-dim);
  --text2: var(--text2-dim);
  --surface1: var(--surface1-dim);
  --surface2: var(--surface2-dim);
  --surface3: var(--surface3-dim);
  --surface4: var(--surface4-dim);
  --surface-shadow: var(--surface-shadow-dim);
  --shadow-strength: var(--shadow-strength-dim);
}

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

סיכום

עכשיו, אחרי שסיפרתי לך איך עשיתי את זה, איך היית עושה את זה? 🙂

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

מקור

רמיקסים של הקהילה – ‎@chris-kruining הוסיף פס להזזה של גוון, צבעים של סטטוסים ומצבי ניגודיות עבור no-preference, ‏ more ו-less: הדגמה.