שינויי ירושה של עיצוב בחירת CSS

תאריך פרסום: 8 באוקטובר 2024

החל מגרסה 131 של Chrome, יש שינוי בירושה של הדגשת CSS עבור פסאודו-הקלאסות ::selection ו-::target-text. המטרה היא ליצור מודל אינטואיטיבי יותר לירושה, שתואמת לסוגי השכבות ::highlight,‏ ::spelling-error ו-::grammar-error שנוספו לאחרונה. בפוסט הזה נסביר על השינוי, שאמור לא להשפיע באופן משמעותי על רוב האתרים.

עיצוב הבחירה

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

ב-CSS יש תמיכה בעיצוב של רכיבים שנבחרו באמצעות פסאודו-הרכיב ::selection, אחד מקבוצת פסאודו-רכיבים שנקראים פסאודו-רכיבי הדגשה. אלה רכיבים פסאודו-אלמנטליים ששולטים באופן שבו הטקסט מופיע במסגרת פעולות שונות שמבוססות על משתמשים, דפדפנים או סקריפטים. בנוסף לבחירה, אפשר להוסיף סגנון לשגיאות איות (::spelling-error), לשגיאות דקדוק (::grammar-error), ליעד טקסט שמוטמע בו כתובת URL (::target-text) ולקטעים מודגשים שנוצרו על ידי סקריפט (::highlight).

כמו בכל אוסף של מאפייני CSS, התנהגות הירושה היא שיקול חשוב בתכנון אתר. באופן כללי, מפתחים מצפים שמאפייני CSS יועברו בירושה דרך עץ הרכיבים של DOM (לדוגמה, font), או שלא יועברו בירושה בכלל (לדוגמה, background).

שינויים בהתנהגות הבחירה ב-Chrome 131

נבחן את קטע המסמך הזה:

p {
  color: red;
}

.blue::selection {
  color: blue;
}
<p class="blue">Some <em>emphasized</em> text that one would expect to be blue</p>

הצהרות הסגנון של הקטע משנות את הצבע של הטקסט שנבחר, עם כלל אחד שתואמת לכל הרכיבים וכלל אחד שתואמת לאלה עם הכיתה "blue". כשבוחרים באפשרות הזו ב-Chrome 130 וגרסאות קודמות, התוצאה היא:

טקסט שציפיתם שיהיה כחול הוא אדום.

כשבוחרים באפשרות הזו ב-Chrome 131, התוצאה משתנה כך:

הטקסט מודגש עכשיו בכחול.

מה השתנה? בעבר, התנהגות הירושה של מאפייני הבחירה יושמה באמצעות ירושה מהרכיב המקור, שבה הבחירה משתמשת במאפיינים מ-::selection שתואם לרכיב שנבחר. ב-Chrome בגרסה 130 ואילך נעשה שימוש במודל הזה, שבו לטקסט המודגש אין ::selection תואם כי ה-.blue::selection תואם רק לרכיבים עם הכיתה "blue", ורכיב ה-<em> חסר את הכיתה הזו.

ב-Chrome 131 מופעלת התנהגות חדשה שבה רכיבים יורשים את התנהגות הבחירה מהרכיב ההורה שלהם. בדוגמה הקודמת, לרכיב <em> אין ::selection שתואם לו, ולכן הוא יורש את צבעי הבחירה של רכיב <p>. התכונה הזו נקראת ירושה של הדגשה ב-CSS, וניתן לנסות אותה בגרסאות קודמות של Chrome על ידי הפעלת תכונות ניסיוניות של פלטפורמת האינטרנט בדף chrome://flags.

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

מאפייני CSS מותאמים אישית לבחירה עדיין פועלים

אתרים רבים מדמים את ירושת ההדגשה ב-CSS באמצעות שימוש במאפיינים מותאמים אישית של CSS. מאפיינים מותאמים אישית עוברים בירושה דרך עץ הרכיבים, וכך מקבלים את התוצאה 'inherit from parent' באמצעות קטע קוד כזה:

:root {
   --selection-color: lightgreen;
}

::selection {
  color: var(--selection-color);
}

.blue {
  --selection-color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text that is blue</p>

זו התוצאה כשבוחרים באפשרות הזו גם ב-Chrome 130 וגם ב-131:

השורה הראשונה ירוקה, והשנייה כחולה.

כאן כל רכיב יורש ערך כלשהו של המאפיין --selection-color דרך עץ הרכיבים, והצבע הזה משמש כאשר בוחרים טקסט. רכיבים עם הכיתה .blue והצאצאים שלהם יהיו כחולים כשבוחרים בהם, ורכיבים אחרים יהיו ירוקים בהירים. הרבה אתרים משתמשים בטכניקה הזו, וזו השיטה המומלצת ב-Stack Overflow.

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

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

בוררים אוניברסליים ל-::selection משביתים את ירושת ההדגשה

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

::selection /* = *::selection (universal) */ {
  color: lightgreen;
}

.blue::selection {
  color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text</p>

זו התוצאה כשבוחרים באפשרות הזו גם ב-Chrome 130 (וגרסאות קודמות) וגם ב-Chrome 131 (וגרסאות מתקדמות יותר):

שורת הטקסט הראשונה ירוקה. השנייה כחולה, אבל המילה המודגשת ירוקה.

בירושה של הדגשה ב-CSS, הטקסט השני מודגש לא יורש את הצבע הכחול מההורה שלו כי הבורר האוניברסלי תואם לרכיב <em> ומחיל את צבע ההדגשה האוניברסלי, ירוק בהיר.

כדי ליהנות מהיתרונות של ירושה של הדגשה ב-CSS, משנים את הבורר האוניברסלי כך שיתאים רק לשורש, שיעבור בירושה לצאצאים שלו:

:root::selection {
  color: lightgreen;
}

.blue::selection {
  color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text</p>

התוצאה ב-Chrome 131 נראית כך:

שורת הטקסט הראשונה ירוקה. השורה השנייה כחולה.

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

גם הסגנון של ::target-text משתנה

כל ההתנהגויות והשינויים המתוארים כאן חלים על רכיב הסימון המשנה ::target-text כמו על ::selection. תרחישים לדוגמה שבהם צריך להגדיר יותר מסגנון טקסט אחד של יעד באתר אחד מוגבלים, והתכונה חדשה למדי, כך שסביר מאוד שההתנהגות של ::target-text באתר לא תשתנה.

מה הסיבה לשינוי?

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

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

רוצה לנסות?

השינויים מוצגים ב-CodePen הבא. אפשר לנסות את התכונה ב-Chrome 131.