שמות CSS שהוגדרו על ידי המחבר ו-DOM של צל: במפרט ובפועל

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

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

מהם שמות CSS שהוגדרו על ידי המחבר?

שמות CSS שהוגדרו על ידי המחבר הם מנגנון תחביר CSS ישן יחסית, שהוצג במקור לכלל @keyframes, שמגדיר <keyframe-name> בתור מזהה מותאם אישית או מחרוזת. המטרה של המושג הזה היא להצהיר על משהו בחלק אחד של גיליון סגנונות, ולהפנות אליו בחלק אחר.

/* "fade-in" is a CSS name, representing a set of keyframes */
@keyframes fade-in {
  from { opacity: 0 };
  to { opacity: 1 }
}

.card {
  /* "fade-in" is a reference to the above keyframes */
  animation-name: fade-in;
}

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

תכונה הצהרת שם הפניה לשם
תמונות מפתח (keyframes) @keyframes animation-name
גופנים @font-face { }
@font-palette-values
font-family
font-palette
הצהרות על נכסים @property
כל הצהרה על נכס מותאם אישית לא רשום
var()
הצגת המעברים view-transition-name
view-transition-class
::view-transition-* רכיבי פסאודו
מיקום של מודעת עוגן anchor-name position-anchor
אנימציה שמבוססת על גלילה view-timeline-name
scroll-timeline-name
animation-timeline
סגנונות רשימה @counter-style list-style
מונים counter-reset
counter-set
counter-increment
שאילתות לגבי קונטיינרים container-name @container
דף page @page

כפי שאפשר לראות בטבלה, לשם של CSS בדרך כלל יש הפניה תואמת ל-CSS. לדוגמה, animation-name הוא הפניה לשם @keyframes. שמות ב-CSS שונים משמות שמוגדרים ב-DOM, כמו מאפיינים ושמות תגים, כי הם מוצהרים ולאחר מכן מתבצעת הפניה אליהם בהקשר של סגנונות העיצוב.

הקשר בין שמות ל-Shadow DOM

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

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

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

איך השמות וה-DOM בצל צריכים לפעול יחד

כדי להבין את הבעיה, כדאי להבין איך החלקים האלה של CSS אמורים לפעול יחד בתיאוריה.

הכלל הכללי

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

חריגה מהכלל: @property

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

איך הכלל אמור לפעול עם ::part

חלקי צל חושפים אלמנט בתוך עץ צל לעץ ההורה שלו. כך עץ ההורה יכול לגשת לאלמנט הזה וגם לעצב אותו באמצעות הרכיב ::part.

מכיוון ש-::part מאפשר לשני היקפי עץ לעצב את אותו רכיב, מצוין הסדר הבא של מפל:

  1. קודם כל, בודקים את הסגנון בהקשר של ההצללה. זהו הסגנון 'ברירת המחדל' של החלק.
  2. לאחר מכן מחילים את הסגנון החיצוני כפי שמוגדר ב-::part. זה הסגנון ה"מותאם אישית" של החלק.
  3. לאחר מכן, מחילים כל סגנון פנימי שמוגדר יחד עם !important. כך אפשר להצהיר על רכיב מותאם אישית שמאפיין מסוים של חלק מסוים לא ניתן להתאמה אישית באמצעות ::part.

פירוש הדבר הוא שאי אפשר להפנות לשמות מתוך DOM הצללים מ-::part, כי ::part הוא סגנון ברמת המארח ולא ברמת הצל. לדוגמה:

// inside the shadow DOM:
@keyframes fade-in {
  from { opacity: 0}
}

// This shouldn't work!
// The host style shouldn't know the name "fade-in"
::part(slider) {
  animation-name: fade-in;  
}

איך הכלל אמור לפעול עם סגנונות בקוד

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

איך שמות CSS ו-DOM של הצללים פועלים יחד במציאות

הכללים הקודמים מוגדרים היטב ועקביים, אבל ההטמעות הנוכחיות לא תמיד משקפות זאת. בפועל, @property פועל בצורה שונה מהמפרט באופן עקבי בכל הדפדפנים, וברוב התכונות האחרות יש באגים פתוחים (חלק מהן עדיין לא פורסמו, כך שיש זמן לתקן אותן).

כדי לבדוק ולהדגים איך התכונות האלה פועלות בפועל, יצרנו את הדף הבא: https://css-names-in-the-shadow.glitch.me/. בדף הזה יש כמה iframes, שכל אחד מהם מתמקד באחת מהתכונות ובוחן שישה תרחישים:

  • הפניה חיצונית לשם חיצוני: אין DOM בצל מעורב, זה אמור לפעול.
  • הפניה חיצונית לשם פנימי: הפעולה הזו לא אמורה לפעול, כי זה אומר שהשם שהוגדר בהקשר הצל הדלף.
  • הפניה פנימית לשם חיצוני: זה אמור לפעול, כי שמות ברמת העץ עוברים בירושה לשורשי צל.
  • הפניה פנימית לשם הפנימי: זה אמור לעבוד כי שני השמות של קובץ העזר נמצאים באותו היקף.
  • ::part הפניה לשם החיצוני: הפעולה הזו אמורה לפעול, כי גם ::part וגם השם מוצהרים באותו היקף.
  • ::part הפניה לשם פנימי: הפעולה הזו לא אמורה לפעול, כי ההיקף החיצוני לא אמור לקבל מידע על שמות שהוגדרו בתוך DOM הצל.

@keyframes

כפי שמוגדר במפרט, אפשר להפנות לשמות של תמונות מפתח מתוך שורש צל, כל עוד כלל at-rule‏ @keyframes נמצא בהיקף של אב קדמון. בפועל, אף דפדפן לא מטמיע את ההתנהגות הזו, וניתן להפנות להגדרות של נקודות המפתח רק בהיקף שבו הן מוגדרות. בעיה מס' 10540

@property

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

באגים ספציפיים לדפדפן

התכונות האחרות לא מציגות התנהגות עקבית בדפדפנים השונים:

  • @font-face מוצג ברמת הבסיס (root) ב-Safari.
  • ב-Chromium אסור לרשת כללים של anchor-name ברמה של root בצל
  • ההיקף של scroll-timeline-name ו-view-timeline-name לא תקין ב-::part (גם ב-Chromium).
  • אף דפדפן לא מאפשר להצהיר על @font-palette-values בשורשי צל.
  • אפשר להגדיר את view-transition-class בתוך root בצל (המעבר עצמו נמצא מחוץ ל-root בצל).
  • ב-Firefox, ל-::part יש גישה לשמות של צללים פנימיים (שאילתות של מאגרים, פריימים מרכזיים).
  • בדפדפנים Firefox ו-Safari לא מתייחסים ל-@counter-style ברמה של root בצל.

הערה: ל-counter-reset, ל-counter-set ול-counter-increment יש כללים שונים במקצת כי הם שמות משתמעים, ולהצהרה על מאפייני CSS יש קבוצת כללים מוגדרת ובדיקה היטב.

סיכום

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