Largest Contentful Paint (LCP)

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

  • Chrome: 77.
  • Edge: ‏ 79.
  • Firefox: 122.
  • Safari: לא נתמך.

מקור

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

בעבר, המלצנו על מדדי ביצועים כמו First Meaningful Paint‏ (FMP) ו-Speed Index‏ (SI) (שניהם זמינים ב-Lighthouse) כדי לעזור לתעד יותר מחוויות הטעינה אחרי ה-paint הראשוני, אבל המדדים האלה מורכבים, קשה להסביר אותם ולרוב הם שגויים – כלומר, הם עדיין לא מזהים מתי התוכן הראשי של הדף נטען.

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

מהו LCP?

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

מהו ציון LCP טוב?

כדי לספק חוויית משתמש טובה, צריך לשאוף שהזמן של המדד Largest Contentful Paint יהיה 2.5 שניות או פחות. כדי לוודא שאתם עומדים ביעד הזה עבור רוב המשתמשים, סף טוב למדידה הוא הפרמטר 75th percentile של טעינת הדפים, שמפולח לפי מכשירים ניידים ומחשבים.

ערכים טובים של LCP הם 2.5 שניות או פחות, ערכים גרועים הם יותר מ-4.0 שניות וכל ערך בטווח שביניהם צריך שיפור
ערך LCP טוב הוא 2.5 שניות או פחות.

אילו רכיבים נלקחים בחשבון?

כפי שמפורט כרגע ב-Largest Contentful Paint API, סוגי הרכיבים שנלקחים בחשבון לצורך המדד 'המהירות שבה נטען רכיב התוכן הכי גדול' הם:

  • רכיבי <img> (זמן הצגת המסגרת הראשונה משמש לתוכן אנימציה, כמו קובצי GIF או קובצי PNG עם אנימציה)
  • רכיבי <image> בתוך רכיב <svg>
  • רכיבי <video> (משתמשים בזמן הטעינה של תמונת הפוסטרים או בזמן הצגת הפריים הראשון בסרטונים – המוקדם מביניהם)
  • אלמנט עם תמונת רקע שנטענת באמצעות הפונקציה url() (בניגוד לשיפוע CSS)
  • אלמנטים ברמת הבלוק שמכילים צמתים של טקסט או רכיבי טקסט אחרים ברמת השורה.

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

בנוסף לכך שמדדי LCP מתייחסים רק לחלק מהאלמנטים, הם משתמשים בהיגוריית כדי להחריג אלמנטים מסוימים שהמשתמשים צפויים לראות כ'לא מכילים תוכן'. בדפדפנים מבוססי Chromium, אלה כוללים:

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

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

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

איך נקבע הגודל של רכיב?

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

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

ברכיבי טקסט, המדד LCP מתייחס רק למלבן הקטן ביותר שיכול להכיל את כל צמתי הטקסט.

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

מתי מתבצע דיווח על LCP?

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

כדי לטפל באפשרות לשינוי כזה, הדפדפן שולח אירוע PerformanceEntry מסוג largest-contentful-paint שמזהה את רכיב התוכן הגדול ביותר ברגע שהדפדפן מצייר את המסגרת הראשונה. אבל לאחר מכן, אחרי שרינדור של המסגרות הבאות, הוא ישלח PerformanceEntry נוסף בכל פעם שהרכיב עם התוכן הגדול ביותר ישתנה.

לדוגמה, בדף עם טקסט ותמונה ראשית, הדפדפן עשוי להציג בהתחלה רק את הטקסט. בשלב הזה, הדפדפן ישלח רשומה largest-contentful-paint שבה סביר להניח שהנכס element יפנה ל-<p> או ל-<h1>. מאוחר יותר, אחרי שתמונת ה-Hero תסתיים לטעינת, תישלח רשומה שנייה של largest-contentful-paint, ונכס ה-element שלה יפנה ל-<img>.

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

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

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

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

למטרות ניתוח, צריך לדווח לשירות הניתוח רק על PerformanceEntry שנשלח לאחרונה.

זמן הטעינה לעומת זמן העיבוד

מטעמי אבטחה, חותמת הזמן של עיבוד התמונות לא נחשפת בתמונות ממקורות שונים שחסרה בהן הכותרת Timing-Allow-Origin. במקום זאת, רק זמן הטעינה שלהם נחשף (כי הוא כבר נחשף דרך ממשקי API רבים אחרים לאינטרנט).

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

כשהדבר אפשרי, מומלץ תמיד להגדיר את הכותרת Timing-Allow-Origin כדי שהמדדים יהיו מדויקים יותר.

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

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

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

דוגמאות

ריכזנו כאן כמה דוגמאות למקרים שבהם אירוע ה-Largest Contentful Paint מתרחש בכמה אתרים פופולריים:

ציר זמן של Largest Contentful Paint מ-cnn.com
ציר זמן של LCP מ-cnn.com.
ציר הזמן של Largest Contentful Paint מ-techcrunch.com
ציר זמן של LCP מ-techcrunch.com.

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

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

ציר זמן של Largest Contentful Paint מ-instagram.com
ציר זמן של LCP מ-instagram.com.
ציר זמן של Largest Contentful Paint מ-google.com
ציר זמן של LCP מ-google.com.

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

איך מודדים את מדד LCP

אפשר למדוד את LCP במעבדה או בשטח, והוא זמין בכלים הבאים:

כלים לשדה

כלי Labs

מדידת LCP ב-JavaScript

כדי למדוד את LCP ב-JavaScript, אפשר להשתמש ב-Largest Contentful Paint API. בדוגמה הבאה מוסבר איך ליצור PerformanceObserver שמקשיב לרשאות largest-contentful-paint ומתעדים אותן ביומן במסוף.

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('LCP candidate:', entry.startTime, entry);
  }
}).observe({type: 'largest-contentful-paint', buffered: true});

בדוגמה שלמעלה, כל רשומה ב-largest-contentful-paint ביומן מייצגת את המועמד הנוכחי ל-LCP. באופן כללי, הערך של startTime ברשומה האחרונה שמונפקת הוא הערך של LCP – אבל זה לא תמיד המצב. לא כל הרשומות של largest-contentful-paint תקפות למדידת LCP.

בקטע הבא מפורטים ההבדלים בין מה שמדווח ב-API לבין אופן החישוב של המדד.

ההבדלים בין המדד לבין ה-API

  • ה-API ישלח רשומות largest-contentful-paint לדפים שנטענו בכרטיסייה ברקע, אבל צריך להתעלם מהדפים האלה בזמן חישוב ה-LCP.
  • ה-API ימשיך לשלוח רשומות largest-contentful-paint אחרי שהדף יועבר לרקע, אבל צריך להתעלם מהרשומות האלה כשמחשבים את LCP (אפשר להביא בחשבון רכיבים רק אם הדף היה בחזית כל הזמן).
  • ה-API לא מדווח על רשומות largest-contentful-paint כשהדף משוחזר מהמטמון של 'הקודם'/'הבא', אבל צריך למדוד את LCP במקרים האלה כי המשתמשים חווים אותם כביקור נפרד בדף.
  • ה-API לא מתייחס לרכיבים בתוך iframe, אבל המדד כן מתייחס אליהם כי הם חלק מחוויית המשתמש בדף. בדפים עם LCP בתוך iframe – לדוגמה, תמונת פוסטרים בסרטון מוטמע – הנתון הזה יופיע כהבדל בין CrUX לבין RUM. כדי למדוד את LCP בצורה נכונה, כדאי להביא בחשבון את הגורמים האלה. מסגרות משנה יכולות להשתמש ב-API כדי לדווח על הרשומות שלהן ב-largest-contentful-paint למסגרת ההורה לצורך צבירת נתונים.
  • ה-API מודד את LCP מתחילת הניווט, אבל בדפים שעברו רינדור מראש צריך למדוד את LCP מ-activationStart, כי זהו הזמן של LCP כפי שהמשתמש חווה אותו.

במקום לזכור את כל ההבדלים העדינים האלה, מפתחים יכולים להשתמש בספריית JavaScript של web-vitals כדי למדוד את LCP, והיא מטפלת בהבדלים האלה בשבילכם (במקרים שבהם זה אפשרי – שימו לב שהבעיה של iframe לא מכוסה):

import {onLCP} from 'web-vitals';

// Measure and log LCP as soon as it's available.
onLCP(console.log);

בקוד המקור של onLCP() מופיעה דוגמה מלאה למדידת LCP ב-JavaScript.

מה קורה אם הרכיב הגדול ביותר הוא לא החשוב ביותר?

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

איך משפרים את LCP

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

מקורות מידע נוספים

יומן שינויים

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

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

אם יש לכם משוב לגבי המדדים האלה, אתם יכולים לשלוח אותו לקבוצת Google‏ web-vitals-feedback.