The CSS Podcast - 003: Specificity
נניח שאתם עובדים עם קוד ה-HTML וה-CSS הבא:
<button class="branding">Hello, Specificity!</button>
.branding {
color: blue;
}
button {
color: red;
}
בדוגמה הזו יש שני כללים שמטרגטים את אותו אלמנט. כל כלל מכיל הצהרה שמנסה להגדיר את הצבע של הכפתור: אחד מנסה לצבוע את הכפתור באדום והשני מנסה לצבוע אותו בכחול. איזו הצהרה מוחלת על הרכיב?
הבנת אלגוריתם הספציפיות של CSS היא המפתח להבנת האופן שבו CSS מחליט בין הצהרות מתחרות.
מידת הספציפיות היא אחד השלבים הייחודיים של ה-cascade, שעליו דיברנו במודול הקודם, בנושא ה-cascade.
דירוג הספציפיות
כל כלל בחירה במקור מקבל ניקוד. אפשר לחשוב על הספציפיות כציון כולל, וכל סוג של סלקטור מקבל נקודות לציון הזה. ההצהרות מהכללים עם הספציפיות הכי גבוהה הן אלה שמובילות.
בפרויקט אמיתי, כדי להשתמש בספציפיות בצורה יעילה, צריך לוודא שכללי ה-CSS שרוצים להחיל אכן חלים,ובמקביל לשמור על ערכים נמוכים כדי למנוע מורכבות. הספציפיות צריכה להיות ברמה הנדרשת בלבד, ולא ברמה הגבוהה ביותר שאפשר. יכול להיות שבעתיד יהיה צורך להחיל CSS חשוב יותר. אם תבחרו את רמת הספציפיות הכי גבוהה, יהיה קשה לבצע את המשימה.
הספציפיות היא לא מספר עשרוני אלא טריאדה שמורכבת משלושה רכיבים: A, B ו-C.
-
A: ספציפיות כמו מזהה B: ספציפיות כמו של מחלקה-
C: ספציפיות כמו של רכיב
היא מיוצגת לעיתים קרובות באמצעות הסימון (A,B,C). לדוגמה: (1,0,2).
גם הסימון החלופי A-B-C נפוץ.
איך משווים בין רמות ספציפיות
כדי להשוות בין רמות הספציפיות, משווים בין שלושת הרכיבים לפי הסדר הבא: רמת הספציפיות עם ערך A גדול יותר היא ספציפית יותר. אם שני ערכי A זהים, רמת הספציפיות עם ערך B גדול יותר היא ספציפית יותר. אם גם שני ערכי B זהים, רמת הספציפיות עם ערך C גדול יותר היא ספציפית יותר. אם כל הערכים זהים, רמות הספציפיות שוות.
לדוגמה, (1,0,0) נחשב ספציפי יותר מ-(0,4,3) כי הערך של A ב-(1,0,0) (שהוא 1) גדול מהערך של A ב-(0,4,3) (שהוא 0).
הסלקטורים משפיעים על הספציפיות
כל חלק בשלישיית הספציפיות מתחיל בערך 0, ולכן הספציפיות שמוגדרת כברירת מחדל היא (0,0,0).
כל חלק בסלקטור מגדיל את הספציפיות, ובהתאם לסוג הסלקטור, מגדיל את הערך של A, B או C.
בורר אוניברסלי
סלקטור אוניברסלי (*)
לא מוסיף ספציפיות, והערך שלו נשאר הספציפיות הראשונית של (0,0,0).
* {
color: red;
}
בורר של רכיב או פסאודו-רכיב
סלקטור של רכיב (סוג)
או של פסאודו-רכיב
מוסיף ספציפיות שדומה לזו של רכיב, וכך מגדיל את הרכיב C ב-1.
בדוגמאות הבאות, רמת הספציפיות הכוללת היא (0,0,1).
בורר סוג
div {
color: red;
}
בורר פסאודו-אלמנטים
::selection {
color: red;
}
בורר מחלקה, בורר פסאודו-מחלקה או בורר מאפיינים
סלקטור של class, pseudo-class או attribute מוסיף ספציפיות שדומה ל-class, שמעלה את הרכיב B ב-1.
בדוגמאות הבאות, רמת הספציפיות היא (0,1,0).
בורר הכיתות
.my-class {
color: red;
}
בורר פסאודו-מחלקות
:hover {
color: red;
}
בורר מאפיינים
[href='#'] {
color: red;
}
בורר מזהים
בורר מזהה מוסיף ספציפיות שדומה למזהה, שמגדילה את רכיב A ב-1, כל עוד משתמשים בבורר מזהה (#myID) ולא בבורר מאפיינים ([id="myID"]).
בדוגמה הבאה, הספציפיות היא (1,0,0)
#myID {
color: red;
}
בוררים אחרים
יש הרבה סלקטורים ב-CSS. לא כל המילים האלה מוסיפות ספציפיות.
לדוגמה, פסאודו-הסיווג :not() לא מוסיף כלום לחישוב הספציפיות.
הספציפיות של פסאודו-הסלקטור :not() מוחלפת בספציפיות של הסלקטור הספציפי ביותר בארגומנט הסלקטורים המופרד בפסיקים; הספציפיות זהה לספציפיות שהייתה מתקבלת אם היה כתוב :not(:is(argument)).
div:not(.my-class) {
color: red;
}
גם פסאודו-המחלקות :is() לא מוסיפות לחישוב הספציפיות. בדומה ל-:not(), היא מקבלת את הספציפיות של הארגומנט הספציפי ביותר שלה.
:is(h1, h2, h3) {
color: blue;
}
לדוגמה הזו יש ספציפיות של (0,0,1) כי יש בה רק סוג אחד של סלקטור (type).
אם מוסיפים id, הספציפיות עולה ל-(1,0,0).
:is(h1, h2, h3, #my-heading) {
color: blue;
}
הפסאודו-קלאס :where() שונה. לא משנה כמה ספציפיים הארגומנטים שלו, תמיד יש לו ספציפיות של (0,0,0).
:where(h1, h2, h3, #my-heading)