«من روی دکمه Yes کلیک کردم، چرا روی No کلیک شد؟!»
همه ما این تجربه را در زمان وبگردی و گشتوگذار در سایتهای مختلف داشتهایم؛ این که در زمان لود شدن سایت، بخشهای مختلف آن جابهجا میشوند. این تجربه برای همه ما ناخوشایند است. وقتی از CLS حرف میزنیم، دقیقا منظورمان همین تجربه شماست.
CLS یا Cumulative Layout Shift یک معیار مهم و کاربرمحور برای سنجش ثبات تصویری است. این معیار، میزان تغییرات چیدمان غیرمنتظره صفحات وب را اندازهگیری میکند. یک CLS پایین، به ما این اطمینان را می دهد که صفحه وبسایتمان در زمان بارگذاری، پرش چندانی ندارد و این موضوع میتواند تجربه کاربری خوبی ایجاد کند.
آیا تا به حال برایتان پیش آمده که مقالهای را بهصورت آنلاین بخوانید و ناگهان چیزی در صفحه تغییر کند؟ بدون هیچ هشداری، متن شروع میکند به حرکت کردن و شما یادتان میرود کجا بودید. یا حتی از این بدتر: میخواهید یک لینک یا دکمه را لمس کنید، اما درست قبل از رسیدن انگشت شما به صفحه – بووم! – لینک حرکت میکند و آخر سر انگشت شما چیز دیگری را هدف میگیرد!
در این مقاله از تریبون، بزرگترین پلتفرم انتشار رپورتاژ آگهی، قراره در مورد این مبحث مهم یاد بگیریم و نحوه رفع خطای CLS را بیاموزیم.
بعضی وقتها این تجربهها فقط اعصابمان را خَرد میکنند، اما در مواردی هم میتوانند آسیب جدی به بار بیاورند.
CLS معیاری است که به شما کمک میکند تا تعداد دفعات پرش بخشهای مختلف صفحه در زمان مشاهده سایت توسط کاربران واقعی را اندازهگیری کنید.
در این مقاله با مطالب زیر آشنا میشوید:
ToggleCLS چیست؟
همانطور که در بالا اشاره کردیم، CLS معیاری برای اندازهگیری ثبات بصری در زمان بارگذاری یک صفحه است و به عنوان یک معیار برای تغییر غیرمنتظره عناصر یک صفحه در زمان لودن شدن سایت برای کاربر، معرفی میشود.
CLS زمانی اتفاق میافتد که یک عنصر بصری، موقعیت خود را از یک فریم به فریم دیگر تغییر میدهد.
امتیاز CLS چیست؟
برای این که تجربه کاربری خوبی در سایت ایجاد کنید، باید امتیاز CLS خود را در حد 0.1 یا کمتر نگه دارید. برای این که مطمئن شوید میتوانید به این هدف دست یابید، اندازهگیری ۷۵ درصد لود شدن صفحهها در موبایل و دسکتاپ (به صورت مجموع) میتواند یک اندازه مناسب و استاندارد باشد.
جزئیات تغییرات چیدمان
تغییرات چیدمان از طریق Layout Instability API تعریف میشوند. ورودیهای layout-shift هر بار که تصویری درون محدوده دید، موقعیت اولیه خود را بین دو فریم تغییر میدهد، گزارش میکنند. این نوع از عناصر به عنوان عناصر ناپایدار در نظر گرفته میشوند.
بهتر است به این نکته توجه داشته باشید که layout-shiftها فقط زمانی اتفاق میافتند که عناصر موجود، موقعیت اولیه خود را تغییر دهند. برای همین اگر یک عنصر جدید به صفحه اضافه شود یا اندازه یکی از عناصر موجود تغییر کند، این موارد layout-shift به حساب نمیآید؛ حداقل تا زمانی که این تغییر باعث نشود تا عناصرِ بصریِ دیگر، موقعیت اولیه خود را تغییر دهند.
نحوه محاسبه امتیاز layout-shift
برای محاسبه امتیاز layout-shift، تمرکز مرورگر روی اندازۀ محدودۀ قابلنمایش کاربر و حرکت عناصر ناپایدار در محدودۀ قابلنمایش بین دو فریم است. امتیاز layout-shift نتیجه اندازهگیری دو مشخصه در این جابهجایی است: ضریب تاثیر (impact fraction) و ضریب فاصله (distance fraction) که در ادامه هر دوی این ضرایب را تعریف میکنیم:
امتیاز layout-shift = ضریب تأثیر * ضریب فاصله
ضریب تاثیر (impact fraction) در CLS
ضریب تأثیر یا impact fraction، میزان تاثیر تصاویر یا متون ناپایدار بین دو فریم در محدوده قابل دید کاربر را محاسبه میکند.
ضریب تاثیر فریم فعلی، شامل پیوند محدودههایِ مرئیِ تمامِ عناصرِ ناپایدار در فریم قبلی و فریم فعلی – بهعنوان ضریبی از تمامِ محدودۀ قابلنمایش کاربر است.
به عنوان مثال در تصویر بالا عنصری وجود دارد که شامل نیمی از محدوده قابلنمایش کاربر در یک فریم است. سپس، در فریم بعدی، این عنصر به 25% از طول محدوده قابلنمایش کاربر تغییر و کاهش پیدا میکند. مستطیل قرمزِ خطچین شده، پیوند محدوده مرئی این عنصر در هر دو فریم را نمایش میدهد که در این مورد، شامل 75% از تمام محدوده قابل مشاهده کاربر میشود. در نتیجه ضریب تأثیر آن هم 0.75 است.
ضریب فاصله (distance fraction)
ضریب دیگری که در این محاسبه نقش دارد، ضریب فاصله است. این ضریب، فاصلهای که عنصر ناپایدار طی کرده را به نسبت محدودۀ قابلنمایش کاربر اندازهگیری میکند. ضریب فاصله، شامل «بیشترین فاصلهای است که هر عنصر ناپایدار در فریم حرکت کرده (چه به صورت افقی چه عمودی)»، تقسیم بر «بیشترین ابعاد محدوده قابلنمایش کاربر (هر کدام از عرض و طول که بیشتر باشد)».
در مثال بالا، بیشترین ابعاد محدوده قابلنمایش کاربر طول بود و عنصر ناپایدار 25% در طول محدوده قابلنمایش کاربر حرکت کرده است که ضریب فاصله آن 0.25 میشود.
پس در این مثال ضریب تاثیر برابر با 0.75 و ضریب فاصله برابر با 0.25 است، با این حساب امتیاز layout-shift برابر میشود با 0.1875
(0.75 * 0.25 = 0.1875)
اوایل امتیاز layout-shift فقط بر اساس ضریب تاثیر محاسبه میشد. ضریب فاصله بعدها برای جلوگیری از جریمه شدن مواردی که در آنها عناصر بزرگ، تغییرات کوچکی داشتند، معرفی شد.
مثال بعدی نشان میدهد چطور افزودن محتوا به یک عنصر موجود، باعث تغییر امتیاز layout-shift میشود.
دکمه «Click Me!» در تصویر بالا به باکس خاکستری با متن سیاه چسبیده و باکس سبز با متن سفید را به پایین (تا حدی که از محدوده قابلنمایش کاربر خارج شود) هُل میدهد.
در این مثال، اندازه باکس خاکستری تغییر میکند، اما موقعیت اولیه آن تغییری ندارد؛ برای همین یک عنصر ناپایدار محسوب نمیشود.
درست است که این دکمه، از پیش در محدوده قابلنمایش کاربر نبوده، ولی موقعیت اولیه در آن تغییری ندارد.
موقعیت اولیه باکس سبز چطور؟
این موقعیت تغییر میکند، از آنجا که بخشی از آن خارج از محدوده قابلنمایش کاربر است، این محدوده نامرئی در محاسبات ضریب تاثیر بهحساب نمیآید. پیوند محدودههای مرئی در باکس سبز در هر دو فریم (با خطچین قرمز مشخص شده) به همان اندازۀ محدوده باکس سبز در فریم اول است؛ یعنی 50% از محدوده قابلنمایش کاربر. به این ترتیب ضریب تأثیر آن 0.5 است.
ضریب فاصله هم با فلش آبی رنگ مشخص شده است. باکس سبز چیزی حدود 14% در محدوده قابلنمایش کاربر حرکت کرده، برای همین ضریب فاصله 0.14 است.
امتیاز layout-shift در این مورد با ضرب این دو ضریب میشود 0.07 (0.14*0.5).
مثال آخر چندین عنصر ناپایدار را مشخص میکند:
در اولین فریم تصویر بالا، چهار نتیجه یک درخواستAPI برای حیوانات وجود دارد که بر اساس حروف الفبا مرتب شدهاند. در فریم دوم، نتایج بیشتری به این لیست اضافه میشود.
اولین مورد در فهرست (یعنی Cat) موقعیت اولیه خود را در دو فریم تغییر نمیدهد، برای همین پایدار است. به شکلی مشابه، آیتمهای جدیدی که به فهرست اضافه شدهاند از قبل در این محدوده نبودهاند، برای همین موقعیت اولیه آنها تغییری نکرده است. اما آیتمهایی که تگ سگ (Dog)، اسب (Horse)، و گورخر (Zebra) دارند، همگی موقعیت اولیه خود را تغییر دادهاند و به همین خاطر عناصر ناپایدار نامیده میشوند.
مستطیلهای نقطهچین شده در تصویر بالا، پیوند این سه عنصر ناپایدار را در محدودههای قبلی و بعدی نمایش میدهند که در این مورد به چیزی حدود 38% از محدوده قابلنمایش کاربر میرسد (ضریب تأثیر آن 0.38 است).
این فلشها، فاصلهای را نشان میدهند که عناصر ناپایدار از موقعیت اولیه خودشان جابجا شدهاند. عنصر «گورخر» که با فلش آبی مشخص شده، بیشتر از همه حرکت کرده تا به حدود 30% از طول محدوده قابلنمایش کاربر برسد. این باعث میشود ضریب فاصله در این مثال 0.3 باشد.
با این حساب، امتیاز layout-shift در آن بر اساس فرمول بالا (0.3*0.38) برابر با 0.1172 است.
layout-shift پیشبینیشده در مقابل غیرمنتظره
این طور نیست که تمام layout-shiftها بد باشند. در واقع بسیاری از اپلیکیشنهای پویای وب، به شکل مداوم موقعیت اولیه عناصر در صفحه را تغییر میدهند.
layout-shift ابداعی کاربر
یک layout-shift فقط وقتی بد است که خلاف انتظار کاربر باشد. از سوی دیگر، layout-shiftهایی که در واکنش به تعامل کاربرند (کلیک کردن یک لینک، فشار دادن یک دکمه، تایپ کردن در یک باکس جستجو و موارد مشابه)، در مجموع خوب محسوب میشوند. حداقل تا زمانی خوب هستند که به اندازه کافی به تعامل نزدیک باشند تا رابطه آنها برای کاربر مشخص شود.
مثلا اگر تعامل یک کاربر باعث فعال شدن یک درخواست شبکه شود که برای کامل شدن مدتی طول میکشد، بهترین کار ایجاد فضایی در همان محدوده و قرار دادن یک نمایشگر لود شدن است تا از layout-shift غیرمنتظره در هنگام کامل شدن درخواست شبکه جلوگیری کند. اگر کاربر متوجه نشود که چیزی برای لود شدن وجود دارد، یا درکی از این نداشته باشد که چه زمانی درخواست آماده میشود، ممکن است در فاصلهای که منتظر مانده، روی چیزی دیگر کلیک کند.
layout-shiftهایی که در فاصله زمانی 500 میلیثانیه از ورود اطلاعات توسط کاربر اتفاق میافتند، دارای پرچم (Flag) تنظیمات hadRecentInput هستند، برای همین از محاسبه آنها صرف نظر میشود.
هشدار: این پرچم فقط برای چیزهایی مثل لمس کردن، کلیک، یا فشار دادن دکمه استفاده میشود. تعاملات ادامهدار مانند اسکرول کردن، کشیدن، برجسته کردن و زوم به عنوان «ورودی اخیر» (recent input) محسوب نمیشوند.
انیمیشنها و انتقالها (Animations and transitions)
انیمیشنها و انتقالها (Animations and transitions) زمانی که بهخوبی مورد استفاده قرار بگیرند، یکی از بهترین روشها برای بهروزرسانی محتوا در صفحه (بدون ایجاد یک تجربه کاربری بد) هستند. محتوایی که ناگهانی و غیرمنتظره در صفحه تغییر کند، همیشه حس بدی به کاربر میدهد. اما محتوایی که به تدریج و طبیعی از یک موقعیت به موقعیت دیگر جابهجا شود، معمولا کاربر را راهنمایی میکند تا بهتر بفهمد چه خبر است و چه اتفاقی در صفحه می افتد.
ویژگی transform در CSS به توسعهدهنده این امکان را میدهد، که عناصر را بدون ایجاد layout-shift به حرکت درآورد:
- به جای تغییر ویژگیهای طول و عرض، از تغییر ابعاد یا transform: scale () استفاده میکند.
- برای تغییر عناصر اطراف، از تغییر دادن ویژگیهای top، right، bottom یا left اجتناب کرده و از فرمان transform: translate () به جای آن استفاده میشود.
نحوه اندازهگیری CLS
CLS هم میتواند به شکل آزمایشی (in the lab) و هم میدانی (in the field) اندازهگیری شود، و این امکان در ابزارهای زیر وجود دارد:
ابزارهای میدانی
- گزارش تجربه کاربری کروم
- اطلاعات سرعت صفحه (PageSpeed Insights)
- سرچ کنسول
- کتابخانه جاوااسکریپ web-vitals
ابزارهای آزمایشی
- کروم دوتولز (Chrome DevTools)
- لایتهاوس (Lighthouse)
- وبپیجتست (WebPageTest)
اندازهگیری CLS در جاوااسکریپت
برای اندازهگیری CLS در جاوااسکریپت میتوانید از API ناپایداریِ چیدمان (Layout Instability API) استفاده کنید. در مثال زیر، نحوه ساخت یک PerformanceObserver را میبینیم که ورودیهای layout-shift را دریافت و جمع کرده و آنها را برای کنسول ارسال میکند:
هشدار: این کد، نحوه ثبت و انباشت ورودیهای غیرمنتظره layout-shift را نشان میدهد. با این حال، اندازهگیری CLS در JavaScript پیچیدهتر است.
در مثال بالا، تمام ورودیهای layout-shift که پرچم hadRecentInput در آنها به صورت اشتباه درآمده، جمع میشوند تا ارزش CLS فعلی را مشخص کنند. در بیشتر موارد، ارزش CLS فعلی در هنگامی که صفحه آپلود میشود، ارزش CLS نهایی آن صفحه محسوب میشود. اما چند استثنای مهم هم وجود دارد:
در ادامه میتوانید فهرست تفاوتها بین چیزی که API گزارش میکند و نحوه محاسبه این معیار را مشاهده کنید.
تفاوتهای بین معیار و API
- اگر صفحه در تمام طول عمرش در حالت پسزمینه قرار داشته باشد، APIنباید هیچ ارزش CLSی را گزارش کند.
- اگر صفحه از back/forward cache بازیابی شده باشد، ارزش CLS آن باید به صفر برگردانده شود. چون کاربران آن را بهعنوان بازدید از صفحهای متمایز تجربه میکنند.
- API، ورودیهای layout-shift را برای تغییراتی که درون فریمها اتفاق میافتد گزارش نمیکند. اما برای اندازهگیری درست CLS لازم است به آنها توجه شود. زیر-فریمها میتوانند برای افزایش شتاب فریم والد (parent frame) از API برای گزارش ورودیهای layout-shift استفاده کنند.
به جز این موارد استثنا، چون CLS تمام طول عمر یک صفحه را اندازهگیری میکند، پیچیدگیهایی هم دارد:
- کاربران ممکن است یک تب را برای مدتی بسیار طولانی – روزها، هفتهها، یا ماهها – باز نگه دارند. در واقع، ممکن است یک کاربر هیچ وقت یک تب را نبندد.
- در سیستم عاملهای موبایل، مرورگرها معمولا بازگشت باز نشدن صفحه در تبهای پسزمینه را اجرا نمیکنند، برای همین باعث میشوند گزارش ارزش «نهایی» CLS دشوار شود.
برای برطرفکردن چنین مواردی، هر بار که یک صفحه در پسزمینه قرار میگیرد، CLS باید گزارش شود؛ همچنین هر بار که صفحه آنلود (unload) میشود هم، باز CLS باید گزارش شود (رویداد visibilitychange هر دو سناریو را پوشش میدهد). سیستمهای تحلیلی که این دادهها را دریافت میکنند، لازم است بعدا ارزش نهایی CLS را در بکاند (backend) محاسبه کنند.
به جای حفظکردن و نسخهبرداری از تمام این موارد، توسعهدهندگان میتوانند از لایبراری جاوااسکریپتِ (JavaScript library) web-vitals استفاده کنند، که تمام موارد بالا را محاسبه میکند:
برای یک مثال جامع نحوه اندازهگیری CLS در JavaScript، میتوانید به کد منبع getCLS مراجعه کنید.
در بعضی موارد (مانند iframeهای متقابل) اندازهگیری CLS در JavaScript امکانپذیر نیست. برای مشاهده جزئیات بیشتر به بخش محدودیتها در کتابخانه web-vitals مراجعه کنید.
آموزش نحوه بهبود CLS
در بیشتر وبسایتها، با توجه به بعضی از اصول راهنما، امکان جلوگیری از همه تغییرات چیدمانهای ناگهانی وجود دارد:
- همیشه تمام مشخصات اندازه عناصر تصویری و ویدئویی را قرار دهید یا در غیراینصورت، فضای مورد نیاز را با چیزی مثل باکسهای قطع تصویر CSS (CSS aspect ratio boxes) پر کنید. این روش تضمین میکند که مرورگر میتواند مقدار صحیح فضای سند را هنگام بارگیری تصویر، بهدرستی به آن اختصاص دهد. توجه داشته باشید که همچنین میتوانید از unsized-media feature policy، برای پیادهسازی این رفتار به مرورگرهایی که از این ضوابط پشتیبانی میکنند، استفاده کنید.
- هیچوقت محتوایی روی محتوای موجود قرار ندهید، مگر این که در واکنش به تعامل کاربر باشد. با انجام این کار اطمینان پیدا میکنید که هر layout-shiftی اتفاق بیافتد، پیشبینیشده خواهد بود.
- انیمیشنهای transform را به انیمیشنهایی که تغییرات چیدمان ایجاد میکنند، ترجیح بدهید. انتقالها را به نوعی انیمیشن کنید که پسزمینه و پیوستگی از یک حالت به حالت دیگر داشته باشند.
ثبت تغییرات
هر از گاهی باگهایی در APIهای مورد استفاده برای اندازهگیری معیارها و گاهی نیز در تعریف خود معیارها کشف میشود. در نتیجه، گاهی بعضی از تغییرات ضرورت پیدا میکند، و این تغییرات میتوانند به عنوان بهینهسازی یا پیشرفت در گزارشهای داخلی و داشبوردهای شما ثبت شوند.
برای این که بتوانید این فرایند را مدیریت کنید، باید تمام تغییرات را چه در به کارگیری و چه در تعریف این معیارها در CHANGELOG ذخیره کنید.
گوگل تغییراتی در معیار CLS ایجاد کرد
گوگل تغییراتی را در نحوه محاسبه CLS ایجاد کرده است. در این تغییر، وقفه session پنجره از 1 ثانیه، به 5 ثانیه تغییر کرده است. گوگل اعلام کرد این تغییرات را برای این انجام داده که «صفحههای با بازدید بیشتر و single page apps، منصفانهتر بررسی شوند».
گوگل میگوید که تصمیم گرفته با پنجرههای حداکثری کوچکتر و محدودتر پیش برود و توضیح داده که این موضوع میتواند امتیاز CLS در core web vitals را تغییر دهد.
ازآنجاکه این بهروزرسانی، CLS صفحات را محدود میکند، هیچ صفحهای در نتیجه آن امتیاز بدتری دریافت نمیکند. بر اساس تحلیل ما، 55% از منابع با تغییر 75 درصدی CLS هیچ تغییری نخواهند داشت؛ چون یا صفحه آنها در حال حاضر هیچ layout-shiftی ندارد یا تغییرات چیدمان آنها از قبل در یک پنجره حداکثر بازدید منفرد و واحد تعریف شده است. با این تغییر، بقیه منابع هم میتوانند در امتیاز خود بهبود 75 درصدی داشته باشند. هر چند بیشتر آنها فقط متوجه یک بهبود جزئی میشوند، اما حدود 3% منابع از ردهبندیهای «نیاز به بهینهسازی» یا «ضعیف» به ردهبندی «خوب» تغییر میکنند. این صفحات، به استفاده از اسکرولرهای نامحدود یا تعداد زیادی بهروزرسانیِ کندِ رابط کاربری گرایش دارند.
به روز رسانی: گوگل در تاریخ 13 آپریل 2021 اعلام کرده که این معیارها را در گزارش سرچ کنسول بهروزرسانی کرده است. گوگل نوشته: «معیار CLS بهروزرسانی شده تا بتواند تصویر دقیقتری از layout-shift در صفحه ارائه دهد. برای همین ممکن است متوجه تغییراتی (عموماً مثبت) در موقعیت CLS صفحه خود شوید که نشاندهنده این آپدیت است.»
منبع: web.dev/cls