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

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

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

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

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