יש כמה נושאים חשובים ובסיסיים ב-CSS שרובנו מבינים רק אחרי כמה פרויקטים שכתבנו עם CSS קשה להבנה וקשה לתחזוקה (בלי להתכוון לכך כמובן).
אחד הנושאים האלה הוא CSS Specificity, בד״כ, אנחנו נתקלים בנושא הזה באחד משני מקרים:
- אמרו לנו מתישהו בתחילת הדרך לא להשתמש ב-
important!
ולהוסיףid
אוclass
לאלמנט שאנחנו רוצים לבחור כי המשקל שלid
הוא הכי כבד ו-class
אחריו. - בעבודה עם theme כלשהו המבוסס על ספריית UI (למשל bootstrap) או קומפוננטה כלשהי שהתקנו באבחת
npm install
ופתאום ראינו משהו כזה כשפתחנו dev-console בניסיון להבין איך לשנות שם style של img (או משהו בסגנון):
div#some-wrapper.of-some-component > .its-inner-child .special-list > li img[src^="/assets/icons/icon-"]{}
ואז אנחנו מוסיפים עוד שורות ל-CSS שלנו ומנסים לדייק את ה-selectors כמה שאפשר ומתפללים לאלוהי ה-w3c שהשורות שהוספנו יהיו ברורות לנו ולאחרים בפעם הבאה שנצטרך להוסיף או לתקן שם משהו.
הבנת המשקל והקדימות שיש לסלקטורים שאנחנו כותבים ב-CSS שלנו יכולה לשנות לגמרי את כמות ואיכות ה-CSS שאנחנו כותבים לעצמנו ולאחרים (בספריות, קומפוננטות וכו׳). במילים אחרות, CSS Specificity זה מה שמסביר איזו הצהרת CSS מתוך סבך ה-CSS שלנו ושל הספריות שאנחנו משתמשים בהן הדפדפן יממש ולמה.
חישוב CSS Specificity
יש 4 קטגוריות של סלקטורים שתוצאת המשקל שלהן תכריע איזו הצהרת CSS הדפדפן יממש:
- תכונת עיצוב (Style Attribute)
- מזהה או Id
- Class, Pseudo-Class, Attribute
- HTML Elements, Pseudo-Elements
אדגים כל קטגוריה מהסלקטורים ה״כבדים״ ל״קלים״ ולאחר מכן אציג כמה דוגמאות לחישוב ואת ספריית החישוב specificity. נהוג להציג משקל של סלקטור באופן המזכיר מערך כאשר הערך הראשון (משמאל לימין) הוא הכבד ביותר. בכל פעם שנציין בכלל ה-CSS שלנו סלקטור מקטגוריה מסויימת נוסיף 1 למקום הרלוונטי במערך. למשל, אם id
שוקל [0,1,0,0] ויש לנו כלל שיש בו שני ids המשקל של הכלל יהיה [0,2,0,0]:
תכונת עיצוב (Style Attribute) – [1,0,0,0]
תכונת style
, או inline style
היא משהו שאנחנו בד״כ רוצים להימנע ממנו ולא רק בגלל שיש לזה פוטנציאל הרסני מבחינת maintainability ו-readability אלא מכיוון שתכונת ה-style מקבלת את את הניקוד הגבוה ביותר בחישוב specificity:
<div style="color: dodgerblue">I’m a cute div</div>
מזהה (id) – [0,1,0,0]
ה-id הוא הסלקטור הבא בתור מבחינת משקל.
<style>
#oy-vey{
color: red;
}
</style>
<div id="oy-vey">oy vey!</div>
Class, pseudo-class, attribute [0,0,1,0]
שלושת הסלקטורים בקטגוריה הזאת שוקלים פחות מ-id. הנה כמה דוגמאות:
כאן אנחנו בוחרים כל אלמנט שיש לו class
של div-me-a-break.
:
<style>
.div-me-a-break{
color: dodgerblue;
}
</style>
<div class="div-me-a-break">these pretzels are making me thirsty!</div>
וכאן אנחנו בוחרים באמצעות pseudo-class
כל li
ראשון:
<style>
li:first-child{
color: dodgerblue;
}
</style>
<ul>
<li>I’m the first li</li>
<li>I’m the second li</li>
</ul>
בדוגמה הבאה אנחנו בוחרים כל תגית <a>
שיש לה attribute
של href
שנגמר ב-pdf.
:
<style>
a[href$=".pdf"]{
color: red;
}
</style>
<a href="/some/link/to/file.pdf">PDF</a>
[0,0,0,1] Elements & Pseudo Elements
הקבוצה האחרונה של סלקטורים היא HTML Elements ו-Pseudo Elements. והנה 2 דוגמאות:
<style>
div {
color: red;
}
</style>
<div>these pretzels are making me thirsty</div>
וכאן אנחנו בוחרים pseudo element:
חישוב CSS Specificity
כמו שראינו למעלה, לכל קטגוריה של סלקטורים יש משקל משלה. נהוג לסמן Specificity מהמשקל הכבד ביותר לקל ביותר כך מבחינת הקטגוריות שסקרנו (משמאל לימין): [1,0,0,0]. כל סלקטור שנפרט יוסיף נקודה למיקום המתאים שלו בסדרה. נדגים. הנה כמה rules וה-specificity score שלהם.
ul li a = [0,0,0,1] + [0,0,0,1] + [0,0,0,1] = [0,0,0,3]
#main article .special-paragraph h2 = [0,1,0,0] + [0,0,0,1] + [0,0,1,0] + [0,0,0,1] = [0,1,1,2]
#another #example .for .you = [0,1,0,0] + [0,1,0,0] + [0,0,1,0] + [0,0,1,0] = [0,2,2,0]
נעבור על דוגמה נוספת – תפריט ניווט. הנה ה-HTML שלנו:
<nav>
<ul class="nav-list">
<li class="nav-item">
<a href="/">Home</a>
</li>
<li class="nav-item">
<a href="/about">About</a>
</li>
</ul>
</nav>
והנה ה-CSS שלנו:
/* [0,0,1,2] */
nav .nav-item a {
color: green;
}
/* [0,0,1,1] */
.nav-item a {
color: powderblue;
}
מה יהיה צבע התוכן של תגית ה-a?
אנחנו יכולים לראות לפי ה-Specificity Score שהצבע יהיה ירוק כי [0,0,1,2] > [0,0,1,1].
ספריית CSS Specificity
יש הרבה ספריות וכלים שעוסקים ב-CSS specificity. אחת הידועות היא, חכו לזה… specificity. ספרייה ותיקה וקטנטנה לחישוב specificity.
איך מתקינים:
npm install specificity
איך משתמשים? כל הפרטים כאן.
והנה דמו קטן שממש את פונקציית ה-calculate של הספרייה להנאתכם:
מקורות נוספים:
- https://csshell.dev/posts/overspecified-specificity/
- https://medium.com/@emmabostian/css-specificity-d5fdb0996c81
- https://css-tricks.com/specifics-on-css-specificity/
- https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
- https://specifishity.com/