משקל של סלקטורים

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

נניח שיש לנו את המבנה הבא:

<ul id="drinks">
  <li class="favorite">Water</li>
  <li>Coffee</li>
  <li>Tea</li>
</ul>

ואנו נותנים את ההגדרות הבאות:

#drinks li{
  color: black;
  font-weight: normal;
}
.favorite{
  color: red;
  font-weight: bold;
  text-decoration: underline;
}

ניתן לראות שהאלמנט favorite לא קיבל את שתי ההגדרות font-weight, color, אלא רק את ההגדרה של text-decoration. שימו לב שעבור שתי ההגדרות שהוא לא קיבל – ישנה הגדרה נוספת שחלה גם עליו – ההגדרה שחלה על הסלקטור #drinks li. יצרנו כאן לדפדפן מעין קונפליקט, שתי הגדרות שאחת אמורה לדרוס את השניה, והוא צריך להכריע מי חשובה יותר, מי שוקלת יותר ואליה להתייחס ולדרוס את האחרת.

כל פעם שאנחנו כותבים סלקטור, על מנת להגדיר עליו הגדרות CSS, יש לכל חלק בסלקטור משקל סגולי כלשהו, כשהסיכום של כלל החלקים של הסלקטור הוא המשקל הסופי שלו. ככל שהמשקל הסופי של הסלקטור גבוה יותר – כך עולה הסיכוי שלו לדרוס סלקטורים אחרים. בדוגמה שנתנו – הסלקטור #drinks li שווה יותר מהסלקטור .favorite, ולכן האחד דורס את השני.

איך משקללים את משקל הסלקטור

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

הדגמת חישוב משקל סלקטורים
(נלקח מהאתר csstricks)
  • הגדרה בתוך שורת הHTML, מה שנקרא style-inline – מנצח באופן אוטומטי. הוא שוקל בעצם 1000.
  • כל ID שיש לנו בסלקטור מוסיף 100 למשקל הסופי
  • כל קלאס, קלאס מדומה (למשל :hover, :first-child וכדו'), וכן מאפיינים ([type="text"] וכו') – כל אחד כזה מוסיף למשל הסופי 10.
  • שם האלמנט – a, span, div וכן שם אלמנט פיקטיבי – :after, :before ועוד – כל אחד מוסיף 1.

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

אם נחזור לדוגמא שאיתה פתחנו:

#drinks li

יש לנו כאן ID אחד = 100, וכן שם אלמנט אחד = 1. יחד זה שוקל 101.

.favorite

כאן יש לנו רק קלאס, לכן הוא שוקל רק 10.

עכשיו נבין למה ההגדרה של .favorite לא דרסה את ההגדרה הקודמת – #drinks li. פשוט כי היא שוקלת פחות ואין לה אפשרות לנצח…

דוגמאות נוספות (צילומי מסך מתוך האתר https://specificity.keegan.st/ הנפלא! שיחשב לכם בקלות מי דורס את מי. שימושי כשאתם צריכים לדרוס הגדרות ארוכות)

capture1

capture

ההגדרה !important

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

li.last{    margin-left: 0px !important; }

ההגדרה הזו דורסת את כל ההגדרות האחרות, כשבעצם הדרך היחידה לגבור עליה היא לתת !important בתוך סלקטור עם משקל גבוה יותר. לכן הטוב ביותר הוא להשתמש בהגדרה הזו רק עבור הגדרות שברור לנו שתמיד או כמעט כמעט תמיד נרצה אותן, ואנחנו לא רוצים ששום דבר אחר ידרוס לנו אותן בטעות. לדוגמא לתת כמו בדוגמא שכאן – עבור האלמנט האחרון שתמיד יהיה ללא שוליים משמאל, וכך גם כשנתן אחר כך לכל הפריטים בתפריט למשל שוליים משמאל, כדי שהם יתרחקו מהאלמנט הבא שלהם – האלמנט האחרון לא יקבל את זה. דוגמה נוספת – כשאנחנו יוצרים CSS עבור מצב ניגודיות צבעים גבוהה, אנחנו בוודאות רוצים לתת צבע צהוב עבור כל הטקסטים, ולכן ניתן !important להגדרת הCSS color: yellow; וכדו'.

כשמשתמשים ב!important חשוב לזכור לתת אותו תחת סלקטור שיהיה לנו קל לדרוס במידת הצורך במקרים שלא תכננו מראש.

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

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

מה קורה כשיש לנו שתי סלקטורים באותו משקל, שאחד צריך לדרוס את השני?

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

.active{
   color: #fff;
}

.active{
   color: red;
}

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

הערות חשובות

  • לסלקטור :not אין משקל בפני עצמו, אלא רק מה שבתוך הסוגריים שלו – הוא שוקל. לדוגמה .foo:not(.bar) שוקל 20 בגלל 2 קלאסים.
  • לסלקטור * (= כל האלמנטים מכל הסוגים) אין משקל.
  • ההגדרה !important דורסת כל דבר, כולל הגדרת style-inline. ניתן לראות אותה בעצם כביכול יש לה משקל סגולי הכי גבוה – 10000.

 

עד כאן להפעם.

שאלות? בעיות בנושאים הקשורים CSS?  רעיונות מקוריים למאמר שאף אחד עוד לא כתב? מלאו את הטופס, או פשוט השאירו הערה ותנו לי לחשוב על זה…

כתוב/כתבי תגובה