תחביר צבע יחסי של CSS

יצירת צבעים חדשים בהתבסס על ערוצים וערכים של צבע אחר.

Adam Argyle
Adam Argyle

ב-Chrome 119 היא תכונת צבעים חזקה מאוד מרמת צבע 5 של CSS. תחביר של צבעים יחסיים יוצר נתיב חלק למניפולציה של צבע בתוך ה-CSS, ומציע דרכים ומעצבים כדי:

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

:root {
  --brand-hue: 300deg;
  --brand-saturation: 75%;
  --brand-lightness: 50%;

  --brand-hsl:
    var(--brand-hue)
    var(--brand-saturation)
    var(--brand-lightness);

  --brand-color: hsl(var(--brand-hsl));

  /* all this work just so I can set the opacity to 50% in a variant */
  --brand-color-variant: hsl(var(--brand-hsl) / 50%);
}

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

:root {
  --brand-color: hsl(300deg 75% 50%);
  --brand-color-variant: hsl(from var(--brand-color) h s l / 50%);
}

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

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

סקירה כללית של התחביר

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

א'
מוצג תרשים של התחביר RGB(מ-r, r g b / alpha) עם חץ
משאירים את החלק העליון של הצבע הירוק ומתמקמים לתחילת הפעולה ב-RGB,
החץ מתפצל ל-4 חיצים שמצביעים על המשתנה הרלוונטי שלהם. 
4 החיצים הם אדום, ירוק, כחול ואלפא. לאדום ולכחול יש ערך 0, ירוק
הוא 128 ואלפא הוא 100%.

בתרשים הקודם מוצג צבע המקור green שעבר המרה במרחב הצבעים של הצבע החדש, הפכו למספרים נפרדים שמיוצגים בתור r, g, b ו-alpha משתנים, שמשתמשים לאחר מכן ישירות כערכי צבע חדשים מסוג rgb().

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

מילת המפתח from

החלק הראשון בתחביר שצריך ללמוד הוא החלק from <color> שנוסף שמציין צבע. הוא יופיע ממש לפני שאתם מציינים את הערכים. הנה קוד דוגמה שבה כל מה שנוסף הוא from green, ממש לפני הערכים ל-rgb() צוינו.

.syntax-introduction_same-colors {
  color: green;
  color: rgb(0 128 0);
  color: rgb(from green r g b);    /* result = rgb(0 128 0) */
}

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

המרת צבעים

בשפה פשוטה יותר, היא ממירה את הערוצים r g ו-b לשימוש צבע.

rgb(from green r g b)           /* r=0 g=128 b=0 */
rgb(from rgb(0 128 0) r g b);   /* r=0 g=128 b=0 */

צבעים ממאפיינים מותאמים אישית

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

rgb(from rgb(255 105 180) r g b) /* ????? */
rgb(from var(--hotpink) r g b)   /* clear */

עובדים במרחב הצבעים המועדף

אתם יכולים לבחור את מרחב הצבעים עם סימון צבעים פונקציונלי.

rgb(from hsl(120 100% 25%) r g b)     /*  r=0   g=128  b=0    */
hsl(from hsl(120 100% 25%) h s l)     /*  h=120 s=100% l=25%  */
hwb(from hsl(120 100% 25%) h w b)     /*  h=120 w=0%   b=50%  */
lch(from hsl(120 100% 25%) l c h)     /*  l=46  c=68   h=134  */

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

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

שלבו, מתאימים, משמיטים וחוזרים על המשתנים

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

rgb(from green g g g)    /* rgb(128 128 128) */
rgb(from green b r g)    /* rgb(0 0 128) */
rgb(from green 0 0 g)    /* rgb(0 0 128) */

אטימוּת כמשתנה

התחביר גם מספק את האטימות כמשתנה בשם alpha. (לא חובה) ואחרי / בסימון הצבעים הפונקציונלי.

rgb(from #00800080 r g b / alpha)             /* alpha=50% */
rgb(from rgba(0,128,0,.5) r g b / alpha)      /* alpha=50% */
rgb(from rgb(0 128 0 / 50%) r g b / alpha)    /* alpha=50% */

משתמשים ב-calc() או בפונקציות CSS אחרות על המשתנים

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

green                              /*  h=120 s=100% l=25%  */
hsl(from green calc(h * 2) s l)    /*  h=240 s=100% l=25%  */

זה כחול כהה! הגוון הוכפל, והפך לגוון של 120 240, משנה את הצבע לחלוטין. הפעולה הזו סובבה את הגוון לאורך הצבע גלגל השיניים, טריק פשוט מאוד עם מרחבי צבעים גליליים כמו HSL, HWB, LCH וגם OKLCH.

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

בדיקה אם הדפדפן תומך

@supports (color: rgb(from white r g b)) {
  /* safe to use relative color syntax */
}

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

בדוגמאות ובתרחישים הבאים יש הרבה תחביר חלופי שאפשר להשיג תוצאות דומות או זהות. הווריאציות האלה מגיעות ממרחבי הצבעים הערוצים שהם מציעים.

בנוסף, בהרבה דוגמאות יוצגו התאמות צבעים עם המלל של by וגם to. צבע שהשתנה ב-by הוא שינוי צבע יחסי; שינוי שמשתמש של המשתנה ומבצע התאמה על סמך הערך הנוכחי שלו. א' שינוי צבע to הוא שינוי מוחלט בצבע; שינוי שלא משתמש של המשתנה, ובמקום זאת מציין ערך חדש לגמרי.

כל ההדגמות מופיעות באוסף Codepen הזה.

הבהרת צבע

The OKLCH , OKLAB XYZ או כמה מרחבי הצבעים sRGB מאפשרים תוצאות צפויות בעת הבהרת הצבעים.

בהיר בשיעור מסוים

בדוגמה הבאה, .lighten-by-25 לוקחת את הצבע blue וממירה אותו ל OKLCH, לאחר מכן מבהיר את הכחול על ידי הגדלת הערוץ l (בהירות) על ידי הכפלה בערך הנוכחי ב-1.25. זה מעביר את הבהירות הכחולה ללבן ב-25%.

.lighten-by-25 {
  background: oklch(from blue calc(l * 1.25) c h);
}

הבהרת ערך מסוים

בדוגמה הבאה .lighten-to-75 לא משתמש בערוץ l כדי שמבהיר את הערך blue, הוא מחליף את הערך לחלוטין ב-75%.

.lighten-to-75 {
  background: oklch(from blue 75% c h);
}

כהה צבע

אותם מרחבי צבעים יעילים בהבהרת הצבעים, הם גם מעולים מכהות.

כהה במידה מסוימת

בדוגמה הבאה, .darken-by-25 לוקחת את הצבע הכחול וממירה אותו ל OKLCH, ואז מכהה את הכחול על ידי הקטנת הערוץ l (בהירות) ב-25% להכפיל את הערך ב-.75. הפעולה הזו דוחפת את הצבע הכחול לשחור ב-25%.

.darken-by-25 {
  background: oklch(from blue calc(l * .75) c h);
}

כהה לערך שצוין

בדוגמה הבאה .darken-to-25 לא משתמש בערוץ l כדי להכהות blue, הוא מחליף את הערך לחלוטין ב-25%.

.darken-to-25 {
  background: oklch(from blue 25% c h);
}

רווייה של צבע

רוויה בכמות

הדוגמה הבאה .saturate-by-50 משתמשת ב-s מ-hsl() כדי להגדיל החיוניות של orchid לפי 50% יחסי.

.saturate-by-50 {
  background: hsl(from orchid h calc(s * 1.5) l);
}

רוויה בכמות ספציפית

בדוגמה הבאה .saturate-to-100 לא משתמש בערוץ s מ- hsl(), הוא מציין את ערך הרוויה הרצוי. במשפט הזה, הרוויה מוגבהת ל-100%.

.saturate-to-100 {
  background: hsl(from orchid h 100% l);
}

הפחתת הרוויה של צבע

הפחתת הרוויה בסכום

בדוגמה הבאה .desaturate-by-half משתמש ב-s מ-hsl() כדי להקטין הרוויה של indigo בחצי.

.desaturate-by-half {
  background: hsl(from indigo h calc(s / 2) l);
}

הפחתת הרוויה לערך ספציפי

במקום להפחית את הרוויה שלהם בכמות מסוימת, ניתן להפחית את הרוויה שלהם עם ערך מסוים. בדוגמה הבאה .desaturate-to-25 יוצר צבע חדש על סמך indigo אבל הרוויה הוגדרה ל-25%.

.desaturate-to-25 {
  background: hsl(from indigo h 25% l);
}

Chroma הגברת צבע

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

.increase-chroma {
  background: oklch(from orange l calc(c + .1) h);
}

שינוי מידת האטימות של צבע

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

התאמה של מידת האטימות

.decrease-opacity-by-25 {
  background: rgb(from lime r g b / calc(alpha / 2));
}

התאמה של מידת האטימות לערך ספציפי

.decrease-opacity-to-25 {
  background: rgb(from lime r g b / 25%);
}

היפוך צבע

היפוך צבעים הוא פונקציה נפוצה להתאמת צבעים שנמצאת בספריות צבעים. דרך אחת לעשות זאת היא להמיר צבע ל-RGB ואז להפחית מהערך של הערוץ מ-1.

.invert-each-rgb-channel {
  background: rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b));
}

הוספת צבע

אם היעד לא היה להפוך צבע אלא להשלים אותו, אז כדאי להוסיף גוון הוא כנראה מה שחיפשתם. לבחור מרחב צבעים שכולל את משתמשים בגוון כזווית ולאחר מכן משתמשים ב-calc() כדי לסובב את הגוון בשיעור הרצוי. במקרה כזה, כדי למצוא תוספת לצבע מסוים, צריך לסובב את הראש בחצי סיבוב אפשר להוסיף או לחסר את הערוץ h ב-180 כדי להשיג את התוצאה.

.complementary-color {
  background: hsl(from blue calc(h + 180) s l);
}

ניגודיות של צבע

כשיטה להשגת יחסי ניגודיות נגישים של צבעים, כדאי להשתמש ב-L&midast; (Lstar). זה משתמש בערוץ הבהירות (L) האחידה בערך (L) LCH ו-OKLCH, ב-calc(). בהתאם לטירגוט: נמוך, בינוני או גבוה לניגודיות, ערך ה-L&midast; דלתא היא בערך 40, בערך 50 או בערך 60.

השיטה הזו פועלת היטב בכל גוון ב-LCH או ב-OKLCH.

ניגודיות צבע כהה יותר

המחלקה .well-contrasting-darker-color מדגימה את L* עם דלתא של 60. מכיוון שצבע המקור הוא צבע כהה (ערך בהיר נמוך), נוסף 60% (.6) לערוץ הקלילות. השיטה הזאת משמשת למציאת ניגודיות טובה, אותו גוון, טקסט כהה על רקע בהיר.

.well-contrasting-darker-color {
  background: darkred;
  color: oklch(from darkred calc(l + .60) c h);
}

ניגודיות לצבע בהיר יותר

המחלקה .well-contrasting-lighter-color מדגימה את L* עם דלתא של 60% גם. מכיוון שצבע המקור הוא צבע בהיר (ערך בהירות גבוה), .60 הוא מופחת מערוץ הבהירות.

.well-contrasting-lighter-color {
  background: lightpink;
  color: oklch(from lightpink calc(l - .60) c h);
}

לוחות צבעים

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

צריך לפתוח את קוד המקור לדוגמה של האפשרויות האלה ולנסות לשנות את --base-color, ל- לראות עד כמה לוחות אלה דינמיים. זה כיף!

אם אתם אוהבים סרטונים, אני רוצה לספק לכם מידע מפורט על פיתוח לוחות צבעים ב-CSS באמצעות OKLCH ב-YouTube.

לוחות צבעים מונוכרומטיים

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

:root {
  --base-color: deeppink;

  --color-0: oklch(from var(--base-color) calc(l + .20) c h); /* lightest */
  --color-1: oklch(from var(--base-color) calc(l + .10) c h);
  --color-2: var(--base-color);
  --color-3: oklch(from var(--base-color) calc(l - .10) c h);
  --color-4: oklch(from var(--base-color) calc(l - .20) c h); /* darkest */
}
רוצה לנסות כמה לוחות צבעים שנוצרו עם תחביר צבעים יחסי ו-OKLCH

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

לוחות צבעים אנלוגיים

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

:root {
  --base-color: blue;

  --primary:   var(--base-color);
  --secondary: oklch(from var(--base-color) l c calc(h - 45));
  --tertiary:  oklch(from var(--base-color) l c calc(h + 45));
}

לוחות צבעים טריאדיים

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

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

:root {
  --base-color: yellow;
  --triad-1: oklch(from var(--base-color) l c calc(h - 120));
  --triad-2: oklch(from var(--base-color) l c calc(h + 120));
}

לוחות צבעים טטריים

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

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

:root {
  --base-color: lime;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) l c calc(h + 90));
  --color-3: oklch(from var(--base-color) l c calc(h + 180));
  --color-4: oklch(from var(--base-color) l c calc(h + 270));
}

מונוכרומטי עם סיבוב גוון קל

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

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

:root {
  --base-color: deeppink;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) calc(l - .10) c calc(h - 10));
  --color-3: oklch(from var(--base-color) calc(l - .20) c calc(h - 20));
  --color-4: oklch(from var(--base-color) calc(l - .30) c calc(h - 30));
  --color-5: oklch(from var(--base-color) calc(l - .40) c calc(h - 40));
}
כדאי לנסות את הלידרבורד הזה שנוצר באמצעות OKLCH וסיבוב גוונים

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

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

li {
  --_bg: oklch(
    /* decrease lightness as list grows */
    calc(75% - (var(--i) * 5%))

    /* decrease chroma as list grows */
    calc(.2 - (var(--i) * .01))

    /* lightly rotate the hue as the list grows */
    calc(var(--hue) - (var(--i) + 5))
  );
}