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

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

עומס ב-CSS

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

בפעמים האחרונות מפתחים רבים השתמשו במעבדים מראש של CSS, כמו SASS או 'פחות', כדי לפתור את הבעיה הזו באמצעות שימוש במשתנים של מעבדי מידע מראש. למרות שהכלים האלה הגדילו משמעותית את הפרודוקטיביות של המפתחים, למשתנים שבהם הם משתמשים יש חיסרון משמעותי – שהם סטטיים ואי אפשר לשנות אותם בזמן הריצה. הוספת היכולת לשנות משתנים בזמן ריצה לא רק פותחת את הדלת לדברים כמו יצירת נושאים דינמיים של אפליקציות, אלא גם יש לה השלכות משמעותיות על התכנון הרספונסיבי ועל פוטנציאל להשלים תכונות CSS עתידיות. בעקבות ההשקה של 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;

חשוב לזכור שמאפיינים מותאמים אישית הם תלויי אותיות רישיות, לכן --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 */
}

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

<!-- 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'

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