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

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

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

הדגמה

אם ברצונך ליצור סרטון, הנה גרסת YouTube של הפוסט הזה:

סקירה כללית

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

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

המותג

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

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

על מנת לאפשר קונספט של כהה או הבהרת צבע המותג, למשל 20%, יש לשלוף את שלושת הערוצים של ערך הצבע 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;
}

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

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

* {
  --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%, ולהוות ידית עדינה לכוונון במקרה שהציונים נמוכים.

אני קורא לזה "bump til ya Pass": האינטראקציה של הוספת קלות הערך עד שכלי מראה שאני עובר.

לוחצים על 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. הצללית הזו נוצרה בכלי 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: הדגמה.