ניראות (content-visiability): נכס ה-CSS החדש שמשפר את ביצועי הרינדור

אפשר לדלג על הרינדור של תוכן שלא מופיע במסך כדי לשפר את זמן הטעינה הראשונית.

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

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

תמיכה בדפדפנים

תמיכה בדפדפן

  • Chrome: 85.
  • קצה: 85.
  • Firefox: 125.
  • Safari: 18.

מקור

content-visibility מסתמך על קווים ראשוניים בתוך בתוך ה-CSS מפרט. אומנם רק content-visibility נתמך כרגע ב-Chromium 85 (והוא מוגדר כ"ערך יצירת אב טיפוס" עבור Firefox), מפרטי הגבולות נתמכים בגרסה המודרנית ביותר דפדפנים.

אמצעי למניעת זליגת נתונים ב-CSS

המטרה העיקרית והכוללת של אמצעי הבקרה על CSS היא לאפשר שיפורים בביצועי הרינדור של תוכן אינטרנט על ידי ביצוע בידוד צפוי של עץ משנה של DOM משאר הדף.

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

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

  • size: אילוץ הגודל של אלמנט מבטיח שאפשר להציב את התיבה של האלמנט בלי לבדוק את הצאצאים שלו. כלומר, אם כל מה שאנחנו צריכים הוא הגודל של הרכיב, אנחנו יכולים לדלג על הפריסה של הצאצאים.
  • layout: בלימת הפריסה פירושה שצאצאים לא משפיעים על פריסה חיצונית של תיבות אחרות בדף. כך אנחנו יכולים לדלג על פריסת הצאצאים, אם כל מה שאנחנו רוצים לעשות הוא לפרוס תיבות אחרות.
  • style: הגבלת סגנון מבטיחה שמאפיינים שעשויים להשפיע על והם לא רק הצאצאים שלו לא יוצאים מהאלמנט (למשל מונה). הזה היא מאפשרת לנו לדלג על חישוב סגנון עבור הצאצאים, הוא רוצה לחשב סגנונות באלמנטים אחרים.
  • paint: בידוד צבע מבטיח שהצאצאים של התיבה שמכילה את האובייקט להופיע מחוץ לגבולות שלו. אף דבר לא יכול לחרוג מהרכיב באופן גלוי, ואם רכיב נמצא מחוץ למסך או לא גלוי מסיבה אחרת, גם הצאצאים שלו לא יהיו גלויים. כך אנחנו יכולים לדלג על השלב הזה אם הרכיב נמצא מחוץ למסך.

מדלג על עבודה הרינדור עם content-visibility

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

המאפיין 'הרשאות גישה לתוכן' מקבל כמה ערכים, אבל auto הוא שמספק שיפורים מיידיים בביצועים. רכיב שכולל content-visibility: auto מקבל קליטה של layout, style ו-paint. אם המיקום אלמנט החיפוש נמצא מחוץ למסך (ולא רלוונטי למשתמש מסיבה אחרת - רלוונטי) הם אלו שבהם יש מיקוד או בחירה בעץ המשנה), גם מקבל גבול size (והוא מפסיק לפעול ציור וגם מבחן היטים את התוכן שלו).

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

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

הערה לגבי נגישות

אחת התכונות של content-visibility: auto היא שהתוכן שלא מוצג במסך נשאר זמין במודל האובייקטים של המסמך, ולכן עץ הנגישות (לא כמו ב-visibility: hidden). כלומר, ניתן לחפש את התוכן בדף ולנווט אליו, מבלי להמתין לטעינתו או לפגוע בביצועי העיבוד.

עם זאת, הצד ההפוך הוא שרכיבי ציון דרך עם תכונות סגנון כמו display: none או visibility: hidden יופיעו גם בעץ הנגישות כשהם מחוץ למסך, כי הדפדפן לא יציג את הסגנונות האלה עד שהם ייכנסו לאזור התצוגה. כדי שהן לא יופיעו בעץ הנגישות ויגרמו לבעיות בקריאה, חשוב להוסיף גם את aria-hidden="true".

לדוגמה: בלוג בנושא טיולים

בדוגמה הזו אנחנו מחילים את הבלוג שלנו בנושא נסיעות בצד ימין, ומחילים את content-visibility: auto על אזורים במקטעי נתונים בצד שמאל. התוצאות מציגות זמני רינדור, שנעים בין 232 אלפיות השנייה ל-30 אלפיות שנייה בטעינה הראשונית של הדף.

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

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

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

צילום מסך של בלוג בנושא טיולים.
דוגמה לבלוג בנושא טיולים. לעיון בקטע הדגמה ב-Codepen

עכשיו כדאי לחשוב מה יקרה אם תוסיפו את content-visibility: auto לכל אחד סיפורים בודדים בבלוג. הלולאה הכללית זהה: הדפדפן מורידים ומרינדרים קטעי דף. אבל ההבדל כמות העבודה שהוא עושה בשלב 2.

בעזרת האפשרות content-visibility, המערכת תגדיר את העיצוב והפריסה של כל התוכן שגלוי כרגע למשתמש (הוא מופיע במסך). עם זאת, במהלך עיבוד וספר שלא מוצג במסך מלא, הדפדפן ידלג על עבודת הרינדור לעצב ולעצב את תיבת האלמנט עצמה בלבד.

הביצועים של טעינת הדף הזה יהיו כאילו הוא מכיל סיפורים מלאים במסך ותיבות ריקות לכל אחד מהסיפורים שמחוץ למסך. לביצועים האלה יש ביצועים טובים מאוד טוב יותר, עם ירידה צפויה של 50% או יותר מעלות הרינדור של בטעינה. בדוגמה שלנו, אנחנו רואים עלייה מזמן הרינדור של 232 אלפיות השנייה זמן רינדור 30 אלפיות השנייה. מדובר בשיפור של פי 7 בביצועים.

איזו עבודה צריך לעשות כדי ליהנות מיתרונות אלו? קודם כל, חלק את התוכן לחלקים:

צילום מסך עם הערות של קיבוץ התוכן לקטעים באמצעות מחלקה של CSS.
דוגמה לחלוקת תוכן לקטעים עם החלת המחלקה story, כדי לקבל את הערך content-visibility: auto. לעיון בקטע הדגמה ב-Codepen

לאחר מכן, מחילים על הקטעים את כלל הסגנון הבא:

.story {
  content-visibility: auto;
  contain-intrinsic-size: 1000px; /* Explained in the next section. */
}

ציון הגודל הטבעי של רכיב באמצעות contain-intrinsic-size

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

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

למרבה המזל, שירות ה-CSS מספק נכס נוסף, contain-intrinsic-size, מציין את הגודל הטבעי של הרכיב אם הרכיב מושפעות מכמות גדולה מדי. בדוגמה שלנו, אנחנו מגדירים אותו כ-1000px בתור אומדן לגובה ולרוחב של הקטעים.

כלומר, הפריסה תתפרס כאילו היה לו צאצא יחיד בגודל אינטנסיבי" כדי להבטיח שקודי div ללא גודל עדיין תופסים מקום. contain-intrinsic-size משמש כגודל placeholder במקום תוכן שעבר רינדור.

ב-Chromium 98 ואילך, יש auto חדש מילת מפתח עבור contain-intrinsic-size. אם מציינים את הגודל, הדפדפן יזכיר את הגודל האחרון שעבר עיבוד, אם יש כזה, וישתמש בו במקום בגודל של placeholder שסופק על ידי המפתח. לדוגמה, אם ציינתם את הערך contain-intrinsic-size: auto 300px, הרכיב יתחיל עם 300px בגודל מהותי בכל מאפיין, אבל אחרי שהתוכן של הרכיב יומר, הוא ישמור על הגודל המהותי שהומר. גם שינויים עתידיים בגודל הרינדור יישמרו. בפועל, המשמעות היא שאם לגלול רכיב עם content-visibility: auto ואז לגלול אותו חזרה מחוץ למסך, הוא ישמור אוטומטית על הרוחב והגובה האידיאליים שלו, לגודל של ה-placeholder. התכונה הזאת שימושית במיוחד לגלילה מתמשכת, מה שיכול לשפר באופן אוטומטי את הערכת הגודל לאורך זמן, מבקר בדף.

מסתיר תוכן באמצעות content-visibility: hidden

מה אם ברצונך להשאיר את התוכן ללא עיבוד, גם אם לא נמצא במסך, תוך מינוף היתרונות של מצב העיבוד שנשמר במטמון? מזינים: content-visibility: hidden

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

כך יש לך שליטה רבה יותר, ומאפשר לך להסתיר את התוכן ואת לבטל את ההסתרה שלהן מאוחר יותר.

ניתן להשוות זאת לדרכים נפוצות אחרות להסתרת תוכן של אלמנטים:

  • display: none: מסתיר את האלמנט ומשמיד את מצב העיבוד שלו. הזה המשמעות היא שביטול ההסתרה של האלמנט יהיה יקר כמו עיבוד של רכיב חדש עם אותם תכנים.
  • visibility: hidden: מסתיר את האלמנט ושומר את מצב העיבוד שלו. הזה לא באמת מסיר את הרכיב מהמסמך, שכן הוא (והוא עץ המשנה) עדיין תופסת שטח גיאומטרי בדף ועדיין ניתן ללחוץ עליה. הוא גם מעדכן את מצב העיבוד בכל פעם שנדרש, גם כשהרכיב מוסתר.

לעומת זאת, כשמשתמשים ב-content-visibility: hidden, הרכיב מוסתר תוך שמירה על מצב העיבוד שלו. לכן, אם צריך לבצע שינויים, הם מתבצעים רק כשהרכיב מוצג שוב (כלומר, כשהנכס content-visibility: hidden מוסר).

דוגמאות לתרחישים טובים לדוגמה של content-visibility: hidden כאשר מטמיעים באמצעות גלילה וירטואלית מתקדמת ופריסה של מדידה. אפשר להשתמש בהם גם אפליקציות בדף יחיד (SPA). אפשר להשאיר תצוגות לא פעילות של אפליקציות ב-DOM עם החלת content-visibility: hidden כדי למנוע את הצגתן, אבל לשמור את המצב שלהן במטמון. כך התצוגה תעבור עיבוד מהיר כאשר היא תחזור להיות פעילה.

ההשפעה על המדד 'זמן אינטראקציה עד התוכן הבא (INP)'

INP הוא מדד שמעריך את היכולת של דף להגיב באופן מהימן לקלט של משתמשים. רמת התגובה יכולה להיות מושפעת מעבודה רבה מדי על ה-thread הראשי, כולל עבודות רינדור.

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

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

סיכום

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