משתני CSS – למה זה חשוב לכם?

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

עומס CSS

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

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

מאפיינים מותאמים אישית בקצרה

נכסים מותאמים אישית מוסיפים שתי תכונות חדשות לערכת הכלים שלנו ל-CSS:

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

הנה דוגמה מהירה להמחשה

:root {
    --main-color: #06c;
}

#foo h1 {
    color: var(--main-color);
}

--main-color הוא מאפיין מותאם אישית שהוגדר על ידי המחבר, עם הערך #06c. חשוב לזכור שכל המאפיינים המותאמים אישית מתחילים בשני מקפים.

הפונקציה var() מאחזרת את עצמה ומחליפת אותה בערך של הנכס המותאם אישית, וכתוצאה מכך מתקבל הערך color: #06c;. כל עוד הנכס המותאם אישית מוגדר במקום כלשהו בגיליון הסגנונות, הוא אמור להיות זמין לפונקציה var.

התחביר עשוי להיראות קצת מוזר בהתחלה. מפתחים רבים שואלים, "למה לא להשתמש ב-$foo בשמות המשתנים?" הגישה נבחרה במיוחד כדי שתהיה גמישה ככל האפשר, ויכול להיות שתאפשר להשתמש במאקרו של $foo בעתיד. כדי לקבל רקע, אפשר לקרוא את הפוסט הזה של אחד ממחברי המפרט, Tab Atkins.

תחביר של מאפיין מותאם אישית

התחביר של מאפיין מותאם אישית הוא פשוט.

--header-color: #06c;

חשוב לזכור שמאפיינים מותאמים אישית הם תלויי אותיות רישיות (case-sensitive), כך ש---header-color ו---Header-Color הם מאפיינים מותאמים אישית שונים. התחביר המותר למאפיינים מותאמים אישית נראה פשוט, אבל הוא למעשה די גמיש. לדוגמה, זהו נכס מותאם אישית תקין:

--foo: if(x > 5) this.width = 10;

הנתון הזה לא שימושי כמשתנה, כי הוא לא תקף במאפיין רגיל, אבל אפשר לקרוא אותו ולבצע פעולות באמצעות JavaScript בזמן הריצה. כלומר, נכסים מותאמים אישית יכולים לאפשר שימוש בכל מיני שיטות מעניינות שלא ניתן להשתמש בהן כרגע במעבדי ה-CSS הקיימים. אז אם אתם חושבים "יאוש יש לי SASS אז מי אכפת…", כדאי לכם לבדוק שוב! אלה לא המשתנים שאתם רגילים לעבוד איתם.

המפל

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

:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id="alert">
    While I got red set directly on me!
    <p>I’m red too, because of inheritance!</p>
</div>

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

:root {
    --gutter: 4px;
}

section {
    margin: var(--gutter);
}

@media (min-width: 600px) {
    :root {
    --gutter: 16px;
    }
}

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

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

:root {
    --primary-color: red;
    --logo-text: var(--primary-color);
}

הפונקציה var()‎

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

var(<custom-property-name> [, <declaration-value> ]? )

כאשר <custom-property-name> הוא השם של מאפיין מותאם אישית שהוגדר על ידי המחבר, כמו --foo, ו-<declaration-value> הוא ערך חלופי שישמש כאשר המאפיין המותאם אישית שמצוין לא חוקי. ערכים חלופיים יכולים להיות רשימה מופרדת בפסיקים, שתשולב לערך יחיד. לדוגמה, var(--font-stack, "Roboto", "Helvetica"); מגדיר חלופה ל-"Roboto", "Helvetica". חשוב לזכור שערכים מקוצרים, כמו אלה שמשמשים למרווחים ולרווחים פנימיים, לא מופרדים בפסיקים, ולכן חלופה מתאימה לרווח פנימי תיראה כך.

p {
    padding: var(--pad, 10px 15px 20px);
}

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

/* In the component’s style: */
.component .header {
    color: var(--header-color, blue);
}
.component .text {
    color: var(--text-color, black);
}

/* In the larger application’s style: */
.component {
    --text-color: #080;
    /* header-color isn’t set,
        and so remains blue,
        the fallback value */
}

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

<!-- In the web component's definition: -->
<x-foo>
    #shadow
    <style>
        p {
        background-color: var(--text-background, blue);
        }
    </style>
    <p>
        This text has a yellow background because the document styled me! Otherwise it
        would be blue.
    </p>
</x-foo>
/* In the larger application's style: */
x-foo {
    --text-background: yellow;
}

כשמשתמשים ב-var(), יש כמה דברים שכדאי לשים לב אליהם. משתנים לא יכולים להיות שמות של נכסים. לדוגמה:

.foo {
    --side: margin-top;
    var(--side): 20px;
}

עם זאת, זה לא שווה להגדרה margin-top: 20px;. במקום זאת, ההצהרה השנייה לא תקינה והיא נדחית כשגיאה.

באופן דומה, אי אפשר (באופן תמים) ליצור ערך שחלק ממנו מסופק על ידי משתנה:

.foo {
    --gap: 20;
    margin-top: var(--gap)px;
}

שוב, זה לא שווה ערך להגדרה margin-top: 20px;. כדי ליצור ערך, צריך משהו נוסף: הפונקציה calc().

יצירת ערכים באמצעות calc()

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

.foo {
    --gap: 20;
    margin-top: calc(var(--gap) * 1px); /* niiiiice */
}

עבודה עם מאפיינים מותאמים אישית ב-JavaScript

כדי לקבל את הערך של מאפיין מותאם אישית בזמן הריצה, משתמשים ב-method‏ getPropertyValue() של אובייקט CSSStyleDeclaration המחושב.

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>I’m a red paragraph!</p>
/* JS */
var styles = getComputedStyle(document.documentElement);
var value = String(styles.getPropertyValue('--primary-color')).trim();
// value = 'red'

באופן דומה, כדי להגדיר את הערך של מאפיין מותאם אישית בזמן הריצה, משתמשים ב-method‏ setProperty() של האובייקט CSSStyleDeclaration.

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>Now I’m a green paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'green');

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

/* CSS */
:root {
    --primary-color: red;
    --secondary-color: blue;
}
<!-- HTML -->
<p>Sweet! I’m a blue paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'var(--secondary-color)');

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

תמיכה בדפדפנים

בשלב זה, יש תמיכה במאפיינים מותאמים אישית ב-Chrome 49, ב-Firefox 42, ב-Safari 9.1 וב-iOS Safari 9.3.

הדגמה (דמו)

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

קריאה נוספת

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