Cum să remediați problemele de schimbare cumulativă a aspectului (CLS).

Publicat: 2022-03-10
Rezumat rapid ↬ Inițiativa Google Core Web Vitals a luat cu asalt lumea SEO și Web Performance și multe site-uri sunt ocupate să-și optimizeze experiența în pagină pentru a maximiza factorul de clasare. Valoarea Cumulative Layout Shift cauzează probleme multor site-uri, așa că haideți să aruncăm o privire asupra modalităților de a rezolva orice problemă pentru acea valoare.

Cumulative Layout Shift (CLS) încearcă să măsoare acele mișcări șocante ale paginii pe măsură ce conținut nou – fie că este vorba de imagini, reclame sau orice altceva – intră în joc mai târziu decât restul paginii. Acesta calculează un scor pe baza cât de mult din pagină se mișcă în mod neașteptat și cât de des. Aceste schimbări de conținut sunt foarte enervante, făcându-vă să vă pierdeți locul într-un articol pe care ați început să-l citiți sau, și mai rău, făcându-vă să dați clic pe butonul greșit!

În acest articol, voi discuta câteva modele front-end pentru a reduce CLS . Nu voi vorbi prea mult despre măsurarea CLS, deoarece am tratat-o ​​deja într-un articol anterior. Nici nu voi vorbi prea mult despre mecanica modului în care se calculează CLS: Google are o documentație bună în acest sens, iar Ghidul aproape complet pentru schimbarea aspectului cumulativ al lui Jess Peck este o scufundare minunată și profundă în acest sens. Cu toate acestea, voi oferi un mic context necesar pentru a înțelege unele dintre tehnici.

De ce CLS este diferit

CLS este, în opinia mea, cel mai interesant dintre Core Web Vitals, în parte pentru că este ceva pentru care nu l-am măsurat sau optimizat niciodată până acum. Deci, adesea necesită noi tehnici și moduri de gândire pentru a încerca să-l optimizeze. Este o fiară foarte diferită de celelalte două Core Web Vitals.

Privind pe scurt la celelalte două elemente vitale de bază ale web, Largest Contentful Paint (LCP) face exact așa cum sugerează numele său și este mai mult o răsturnare a valorilor anterioare de încărcare care măsoară cât de repede se încarcă pagina. Da, am schimbat modul în care am definit experiența utilizatorului în ceea ce privește încărcarea paginii pentru a analiza viteza de încărcare a conținutului cel mai relevant , dar practic este reutilizarea vechilor tehnici de a ne asigura că conținutul se încarcă cât mai repede posibil. Modul de optimizare a LCP ar trebui să fie o problemă relativ bine înțeleasă pentru majoritatea paginilor web.

First Input Delay (FID) măsoară orice întârziere în interacțiuni și pare să nu fie o problemă pentru majoritatea site-urilor. Optimizarea este de obicei o chestiune de curățare (sau de reducere!) JavaScript și este de obicei specifică site-ului. Asta nu înseamnă că rezolvarea problemelor cu aceste două valori este ușoară, dar sunt probleme destul de bine înțelese.

Un motiv pentru care CLS este diferit este că este măsurat pe durata de viață a paginii - aceasta este partea „cumulativă” a numelui! Celelalte două Core Web Vitals se opresc după ce componenta principală este găsită pe pagină după încărcare (pentru LCP) sau pentru prima interacțiune (pentru FID). Aceasta înseamnă că instrumentele noastre tradiționale de laborator, cum ar fi Lighthouse, adesea nu reflectă pe deplin CLS, deoarece calculează doar încărcarea inițială CLS. În viața reală, un utilizator va derula în jos pe pagină și poate cădea mai mult conținut, provocând mai multe schimbări.

CLS este, de asemenea, un număr puțin artificial, care este calculat pe baza cât de mult din pagină se mișcă și cât de des. În timp ce LCP și FID sunt măsurate în milisecunde, CLS este un număr fără unități ieșit printr-un calcul complex. Dorim ca pagina să fie 0.1 sau mai mică pentru a trece acest Core Web Vital. Orice lucru peste 0,25 este considerat „slab”.

Schimbările cauzate de interacțiunea utilizatorului nu sunt luate în considerare . Aceasta este definită ca în 500 ms dintr-un anumit set de interacțiuni ale utilizatorului, deși evenimentele pointer și scroll sunt excluse. Se presupune că un utilizator care face clic pe un buton s-ar putea aștepta să apară conținut, de exemplu prin extinderea unei secțiuni restrânse.

CLS este despre măsurarea schimbărilor neașteptate . Derularea nu ar trebui să determine deplasarea conținutului dacă o pagină este construită în mod optim și, în mod similar, trecerea cursorului peste o imagine a unui produs pentru a obține o versiune mărită, de exemplu, nu ar trebui să provoace sărituri în celălalt conținut. Dar există, desigur, excepții și acele site-uri trebuie să ia în considerare cum să reacționeze la acest lucru.

CLS este, de asemenea, în continuă evoluție, cu modificări și remedieri de erori. Tocmai a fost anunțată o schimbare mai mare, care ar trebui să ofere un răgaz paginilor de lungă durată, cum ar fi aplicațiile cu o singură pagină (SPA) și paginile cu defilare infinită, despre care mulți au considerat că au fost penalizate în mod nedrept în CLS. În loc să se acumuleze schimburi de-a lungul întregii pagini de timp pentru a calcula scorul CLS, cum s-a făcut până acum, scorul va fi calculat pe baza celui mai mare set de schimburi dintr-o anumită fereastră timebox.

Aceasta înseamnă că dacă aveți trei bucăți de CLS de 0,05, 0,06 și 0,04, atunci anterior ar fi fost înregistrat ca 0,15 (adică peste limita „bună” de 0,1), în timp ce acum va fi punctat ca 0,06. Este încă cumulativ , în sensul că scorul poate fi alcătuit din schimburi separate în acel interval de timp (adică dacă acel scor 0,06 CLS a fost cauzat de trei schimburi separate de 0,02), dar pur și simplu nu mai este cumulat pe durata de viață totală a paginii. .

Spunând asta, dacă rezolvați cauzele acelei schimbări de 0,06, atunci CLS-ul dvs. va fi raportat ca următorul cel mai mare (0,05), așa că se uită în continuare la toate schimbările de-a lungul vieții paginii - este doar alegerea de a raporta numai cel mai mare ca scorul CLS.

Cu această scurtă introducere a metodologiei despre CLS, să trecem la câteva dintre soluții ! Toate aceste tehnici implică, practic, punerea deoparte a cantității corecte de spațiu înainte de încărcarea conținutului suplimentar - indiferent dacă este vorba de conținut media sau de conținut injectat cu JavaScript, dar există câteva opțiuni diferite disponibile pentru dezvoltatorii web pentru a face acest lucru.

Mai multe după săritură! Continuați să citiți mai jos ↓

Setați lățimea și înălțimea pe imagini și cadre iframe

Am mai scris despre asta, dar unul dintre cele mai simple lucruri pe care le poți face pentru a reduce CLS este să te asiguri că ai setate atributele de width și height pe imagini . Fără ele, o imagine va face ca conținutul ulterior să se schimbe pentru a-i face loc după descărcare:

Un exemplu de aspect cu un titlu și două paragrafe, în care al doilea paragraf trebuie să se deplaseze în jos pentru a face spațiu pentru o imagine.
Schimbarea aspectului după încărcarea imaginii. (Previzualizare mare)

Aceasta este pur și simplu o chestiune de schimbare a marcajului imaginii de la:

 <img src="hero_image.jpg" alt="...">

La:

 <img src="hero_image.jpg" alt="..." width="400" height="400">

Puteți găsi dimensiunile imaginii deschizând DevTools și plasând cursorul peste (sau atingând) elementul.

Captură de ecran Chrome Dev Tools care arată imaginea, dimensiunea redată, raportul de aspect redat, dimensiunea intrinsecă, raportul de aspect intrinseci, dimensiunea fișierului și sursa curentă.
Chrome DevTools afișează dimensiunile imaginii și raporturile de aspect atunci când treceți cu mouse-ul peste un element. (Previzualizare mare)

Vă sfătuiesc să utilizați dimensiunea intrinsecă (care este dimensiunea reală a sursei imaginii), iar browserul le va reduce apoi la dimensiunea redată atunci când utilizați CSS pentru a le modifica.

Sfat rapid : Dacă, la fel ca mine, nu vă amintiți dacă este lățimea și înălțimea sau înălțimea și lățimea, gândiți-vă la coordonatele X și Y, așa că, la fel ca X, lățimea este întotdeauna dată întâi.

Dacă aveți imagini receptive și utilizați CSS pentru a modifica dimensiunile imaginii (de exemplu, pentru a o limita la o max-width de 100% din dimensiunea ecranului), atunci aceste atribute pot fi folosite pentru a calcula height - cu condiția să vă amintiți să o înlocuiți pentru auto în CSS:

 img { max-width: 100%; height: auto; }

Toate browserele moderne acceptă acest lucru acum, deși nu au făcut-o până de curând, așa cum este descris în articolul meu. Acest lucru funcționează și pentru elementele <picture> și imaginile srcset (setați width și height pe elementul img de rezervă), deși nu încă pentru imagini cu diferite raporturi de aspect - se lucrează la aceasta, iar până atunci ar trebui să setați în continuare width și height deoarece orice valoare va fi mai bună decât valorile implicite 0 cu 0 !

Acest lucru funcționează și pentru imaginile native lazy-loaded (deși Safari nu acceptă încărcare nativă leneșă în mod implicit).

Noua proprietate CSS aspect-ratio

Tehnica width și height de mai sus, pentru a calcula înălțimea pentru imaginile receptive, poate fi generalizată la alte elemente folosind noua proprietate CSS aspect-ratio , care este acum acceptată de browserele bazate pe Chromium și Firefox, dar este și în Safari Technology Preview, deci sperăm că asta înseamnă că va ajunge în curând la versiunea stabilă.

Așa că l-ați putea folosi pe un videoclip încorporat, de exemplu, în raport de 16:9:

 video { max-width: 100%; height: auto; aspect-ratio: 16 / 9; }
 <video controls width="1600" height="900" poster="..."> <source src="/media/video.webm" type="video/webm"> <source src="/media/video.mp4" type="video/mp4"> Sorry, your browser doesn't support embedded videos. </video>

Interesant, fără a defini proprietatea aspect-ratio , browserele vor ignora înălțimea elementelor video receptive și vor folosi un raport de aspect implicit de 2:1, așa că este necesar cele de mai sus pentru a evita o schimbare a aspectului aici.

În viitor, ar trebui să fie chiar posibilă setarea dinamică a aspect-ratio pe baza atributelor elementului utilizând aspect-ratio: attr(width) / attr(height); dar din păcate acest lucru nu este încă acceptat.

Sau puteți chiar să utilizați aspect-ratio pe un element <div> pentru un fel de control personalizat pe care îl creați pentru a-l face receptiv:

 #my-square-custom-control { max-width: 100%; height: auto; width: 500px; aspect-ratio: 1; }
 <div></div>

Pentru acele browsere care nu acceptă aspect-ratio puteți utiliza hack-ul mai vechi de padding-bottom, dar, cu simplitatea noului aspect-ratio și suport larg (mai ales odată ce aceasta trece de la Previzualizarea tehnică Safari la Safari obișnuit), este greu de justificat acea metodă mai veche.

Chrome este singurul browser care transmite CLS la Google și acceptă aspect-ratio ceea ce înseamnă că vă va rezolva problemele CLS în ceea ce privește Core Web Vitals. Nu-mi place să dau prioritate valorilor față de utilizatori, dar faptul că celelalte browsere Chromium și Firefox au acest lucru și, sperăm, că Safari va fi în curând și că aceasta este o îmbunătățire progresivă înseamnă că aș spune că suntem în punctul în care poate lăsa în urmă hack-ul de la padding-bottom și poate scrie cod mai curat.

Folosiți în mod liberal min-height

Pentru acele elemente care nu au nevoie de o dimensiune receptivă, ci de o înălțime fixă, luați în considerare utilizarea min-height . Acesta ar putea fi pentru un antet cu înălțime fixă , de exemplu, și putem avea diferite titluri pentru diferitele puncte de întrerupere folosind interogări media ca de obicei:

 header { min-height: 50px; } @media (min-width: 600px) { header { min-height: 200px; } }
 <header> ... </header>

Bineînțeles, același lucru este valabil și pentru min-width pentru elementele plasate orizontal, dar în mod normal, înălțimea este cea care cauzează problemele CLS.

O tehnică mai avansată pentru conținutul injectat și selectoarele CSS avansate este de a viza atunci când conținutul așteptat nu a fost încă inserat. De exemplu, dacă ați avut următorul conținut:

 <div class="container"> <div class="main-content">...</div> </div>

Și un div suplimentar este inserat prin JavaScript:

 <div class="container"> <div class="additional-content">.../div> <div class="main-content">...</div> </div>

Apoi, puteți folosi următorul fragment pentru a lăsa spațiu pentru conținut suplimentar atunci când div-ul main-content este redat inițial.

 .main-content:first-child { margin-top: 20px; }

Acest cod va crea de fapt o schimbare la elementul main-content deoarece marja contează ca parte a acelui element, astfel încât va părea să se schimbe atunci când acesta este eliminat (chiar dacă nu se mișcă de fapt pe ecran). Cu toate acestea, cel puțin conținutul de sub acesta nu va fi mutat, așa că ar trebui să reducă CLS.

Alternativ, puteți utiliza pseudo-elementul ::before pentru a adăuga spațiu pentru a evita deplasarea și pe elementul main-content :

 .main-content:first-child::before { content: ''; min-height: 20px; display: block; }

Dar cu toată sinceritatea, soluția mai bună este să aveți div -ul în HTML și să utilizați min-height pentru asta.

Verificați elementele de rezervă

Îmi place să folosesc îmbunătățirea progresivă pentru a oferi un site web de bază, chiar și fără JavaScript, acolo unde este posibil. Din păcate, acest lucru m-a surprins recent pe un site pe care îl întrețin când versiunea de rezervă non-JavaScript era diferită de când a intrat JavaScript.

Problema s-a datorat butonului de meniu „Cuprins” din antet. Înainte de începerea JavaScript-ului, acesta este un link simplu, stilat astfel încât să semene cu butonul care vă duce la pagina Cuprins. Odată ce JavaScript intră în funcțiune, acesta devine un meniu dinamic care vă permite să navigați direct la orice pagină la care doriți să accesați din pagina respectivă.

Capturi de ecran cu două componente de navigare Cuprins stilate ca un buton. Cu JavaScript, acesta deschide un meniu dinamic, așa cum se arată în a doua imagine.
O componentă antet Cuprins care este redată inițial ca un simplu link (sus) și apoi îmbunătățită cu JavaScript pentru a fi un meniu dinamic (jos). (Previzualizare mare)

Am folosit elemente semantice și, așadar, am folosit un element ancoră ( <a href="#table-of-contents"> ) pentru link-ul de rezervă, dar l-am înlocuit cu un <button> pentru meniul dinamic bazat pe JavaScript. Acestea au fost concepute astfel încât să arate la fel, dar linkul de rezervă era cu câțiva pixeli mai mic decât butonul!

Acesta era atât de mic, iar JavaScript a început de obicei atât de repede, încât nu observasem că era dezactivat. Cu toate acestea, Chrome a observat-o când a calculat CLS și, deoarece acesta era în antet, a deplasat întreaga pagină în jos cu câțiva pixeli. Deci, acest lucru a avut un impact destul de mare asupra scorului CLS - suficient pentru a introduce toate paginile noastre în categoria „Necesită îmbunătățire”.

Aceasta a fost o eroare din partea mea, iar soluția a fost pur și simplu să aduc cele două elemente în sincronizare (ar fi putut fi remediată și prin setarea unei min-height pe antet, așa cum am discutat mai sus), dar m-a confundat puțin. Sunt sigur că nu sunt singurul care a făcut această eroare, așa că fiți conștienți de modul în care se redă pagina fără JavaScript. Nu credeți că utilizatorii dvs. dezactivează JavaScript? Toți utilizatorii dvs. sunt non-JS în timp ce vă descarcă JS.

Fonturile Web provoacă schimbări de aspect

Fonturile web sunt o altă cauză comună a CLS, deoarece browserul calculează inițial spațiul necesar pe baza fontului alternativ, apoi îl recalculează când este descărcat fontul web. De obicei, CLS este mic, cu condiția să fie folosit un font alternativ de dimensiuni similare, așa că adesea nu provoacă o problemă suficientă pentru a eșua Core Web Vitals, dar pot fi totuși supărătoare pentru utilizatori.

Două capturi de ecran ale unui articol Smashing Magazine cu fonturi diferite. Textul are dimensiuni semnificativ diferite și o propoziție suplimentară poate încadra atunci când sunt folosite fonturile web.
Smashing Magazine articol cu ​​font de rezervă și cu fonturi web complete. (Previzualizare mare)

Din păcate, nici măcar preîncărcarea fonturilor web nu va ajuta aici, deoarece, deși asta reduce timpul pentru care sunt folosite fonturile de rezervă (deci este bine pentru performanța de încărcare - LCP), este nevoie de timp pentru a le prelua și, prin urmare, alternativele vor fi în continuare utilizate. de browser în majoritatea cazurilor, deci nu evită CLS. Spunând asta, dacă știți că este nevoie de un font web pe pagina următoare (să spuneți că sunteți pe o pagină de autentificare și știți că pagina următoare folosește un font special), atunci le puteți prelua în prealabil.

Pentru a evita cu totul schimbările de aspect induse de fonturi , bineînțeles că nu am putea folosi fonturi web deloc - inclusiv folosind fonturi de sistem în schimb sau folosind font-display: optional să nu le folosim dacă nu sunt descărcate la timp pentru randarea inițială. Dar niciunul dintre acestea nu este foarte satisfăcător, să fiu sincer.

O altă opțiune este să vă asigurați că secțiunile sunt dimensionate corespunzător (de exemplu, cu min-height ), astfel încât, deși textul din ele se poate schimba puțin, conținutul de sub el nu va fi împins în jos chiar și atunci când se întâmplă acest lucru. De exemplu, setarea unei min-height pentru elementul <h1> ar putea împiedica întregul articol să se deplaseze în jos dacă se încarcă fonturi puțin mai înalte - cu condiția ca diferitele fonturi să nu provoace un număr diferit de linii. Acest lucru va reduce impactul schimburilor, cu toate acestea, pentru multe cazuri de utilizare (de exemplu, paragrafe generice) va fi dificil să se generalizeze o înălțime minimă.

Ceea ce sunt cel mai încântat să rezolv această problemă, sunt noii descriptori de font CSS, care vă permit să ajustați mai ușor fonturile de rezervă în CSS:

 @font-face { font-family: 'Lato'; src: url('/static/fonts/Lato.woff2') format('woff2'); font-weight: 400; } @font-face { font-family: "Lato-fallback"; size-adjust: 97.38%; ascent-override: 99%; src: local("Arial"); } h1 { font-family: Lato, Lato-fallback, sans-serif; }

Înainte de acestea, ajustarea fontului de rezervă era necesară folosind API-ul de încărcare a fonturilor în JavaScript, care era mai complicată, dar această opțiune care va apărea foarte curând ne poate oferi în sfârșit o soluție mai ușoară, care are mai multe șanse să câștige tracțiune. Consultați articolul meu anterior pe acest subiect pentru mai multe detalii despre această inovație viitoare și mai multe resurse despre aceasta.

Șabloane inițiale pentru paginile randate pe partea clientului

Multe pagini randate la nivelul clientului, sau aplicații cu o singură pagină, redă o pagină de bază inițială folosind doar HTML și CSS, iar apoi „hidratează” șablonul după ce JavaScript este descărcat și executat.

Este ușor pentru aceste șabloane inițiale să nu se sincronizeze cu versiunea JavaScript, deoarece componentele și funcțiile noi sunt adăugate aplicației în JavaScript, dar nu sunt adăugate la șablonul HTML inițial care este redat mai întâi. Acest lucru determină apoi CLS atunci când aceste componente sunt injectate de JavaScript.

Prin urmare , examinați toate șabloanele dvs. inițiale pentru a vă asigura că sunt încă substituenți inițiali buni. Și dacă șablonul inițial constă din <div> -uri goale, atunci utilizați tehnicile de mai sus pentru a vă asigura că sunt dimensionate corespunzător pentru a încerca să evitați orice schimbare.

În plus, div -ul inițial care este injectat cu aplicația ar trebui să aibă o min-height pentru a evita ca acesta să fie redat cu înălțimea 0 inițial înainte ca șablonul inițial să fie inserat.

 <div></div>

Atâta timp cât min-height este mai mare decât majoritatea ferestrelor de vizualizare , acest lucru ar trebui să evite orice CLS pentru subsolul site-ului, de exemplu. CLS este măsurat numai atunci când este în fereastra de vizualizare și astfel are impact asupra utilizatorului. În mod implicit, un div gol are o înălțime de 0px, așa că dați-i o min-height care este mai apropiată de înălțimea reală când se încarcă aplicația.

Asigurați-vă că interacțiunile utilizatorului sunt finalizate în 500 ms

Interacțiunile utilizatorilor care determină modificarea conținutului sunt excluse din scorurile CLS. Acestea sunt limitate la 500 ms după interacțiune. Deci, dacă faceți clic pe un buton și faceți o procesare complexă care durează peste 500 ms și apoi redați un conținut nou, atunci scorul dvs. CLS va avea de suferit.

Puteți vedea dacă schimbarea a fost exclusă în Chrome DevTools folosind fila Performanță pentru a înregistra pagina și apoi găsirea schimburilor așa cum se arată în următoarea captură de ecran. Deschideți DevTools accesați fila Performanță foarte intimidantă (dar foarte utilă odată ce o înțelegeți!), apoi faceți clic pe butonul de înregistrare din stânga sus (încercuit pe imaginea de mai jos) și interacționați cu pagina dvs. și opriți înregistrarea o dată complet.

Captură de ecran a Chrome Dev Tools cu o schimbare selectată și rezumatul acesteia arată că a avut o intrare recentă și, prin urmare, schimbarea nu este inclusă în Scorul cumulativ.
Folosind fila Performanță din Chrome Dev Tools pentru a vedea dacă schimburile sunt excluse din cauza intrărilor recente. (Previzualizare mare)

Veți vedea o bandă de film a paginii în care am încărcat unele dintre comentariile la un alt articol Smashing Magazine, așa că în partea pe care am încercuit-o, puteți vedea cum se încarcă comentariile și subsolul roșu este mutat în jos în afara ecranului. Mai jos în fila Performanță , sub linia Experiență , Chrome va pune o casetă roșiatică-roz pentru fiecare tură și când faceți clic pe aceasta, veți obține mai multe detalii în fila Rezumat de mai jos.

Aici puteți vedea că am obținut un scor masiv de 0,3359 - cu mult peste pragul de 0,1 sub care dorim să ne aflăm, dar scorul cumulativ nu a inclus acest lucru, deoarece Had recent input este setat la Utilizări.

Asigurarea interacțiunilor schimbă numai conținutul în limitele de 500 ms pe ceea ce încearcă să măsoare First Input Delay, dar există cazuri în care utilizatorul poate vedea că intrarea a avut un efect (de exemplu este afișat un rotor de încărcare), astfel încât FID este bun, dar conținutul poate nu va fi adăugat la pagină decât după limita de 500 ms, deci CLS este rău.

În mod ideal, întreaga interacțiune se va termina în 500 ms, dar puteți face unele lucruri pentru a rezerva spațiul necesar folosind tehnicile de mai sus în timp ce procesarea respectivă se desfășoară, astfel încât, dacă durează mai mult decât magicul 500 ms, atunci ați s-a ocupat deja de tură și deci nu va fi penalizat pentru asta. Acest lucru este util în special atunci când preluați conținut din rețea care ar putea fi variabil și în afara controlului dumneavoastră.

Alte elemente de care trebuie să aveți grijă sunt animațiile care durează mai mult de 500 ms și, prin urmare, pot afecta CLS. Deși acest lucru ar putea părea puțin restrictiv, scopul CLS nu este de a limita „distracția”, ci de a stabili așteptări rezonabile privind experiența utilizatorului și nu cred că este nerealist să ne așteptăm ca acestea să dureze 500 ms sau mai puțin. Dar dacă nu sunteți de acord sau aveți un caz de utilizare pe care s-ar putea să nu l-ar fi luat în considerare, atunci echipa Chrome este deschisă pentru feedback în acest sens.

JavaScript sincron

Tehnica finală pe care o voi discuta este puțin controversată, deoarece contravine sfatului de performanță web binecunoscut, dar poate fi singura metodă în anumite situații. Practic, dacă aveți conținut despre care știți că va provoca schimbări, atunci o soluție pentru a evita schimbările este să nu îl redați până când nu se stabilește!

HTML-ul de mai jos va ascunde inițial div -ul, apoi va încărca JavaScript de blocare a randării pentru a popula div -ul, apoi îl va afișa. Deoarece JavaScript blochează randarea, nimic de mai jos nu va fi redat (inclusiv al doilea bloc de style pentru a-l ascunde) și, prin urmare, nu vor fi efectuate schimbări.

 <style> .cls-inducing-div { display: none; } </style> <div class="cls-inducing-div"></div> <script> ... </script> <style> .cls-inducing-div { display: block; } </style>

Este important să aliniați CSS-ul în HTML cu această tehnică, așa că este aplicat în ordine. Alternativa este de a ascunde conținutul cu JavaScript în sine, dar ceea ce îmi place la tehnica de mai sus este că încă afișează conținutul, chiar dacă JavaScript eșuează sau este dezactivat de browser.

Această tehnică poate fi aplicată și cu JavaScript extern, dar acest lucru va cauza mai multă întârziere decât un script inline, deoarece JavaScript extern este solicitat și descărcat. Această întârziere poate fi redusă la minimum prin preîncărcarea resursei JavaScript, astfel încât să fie disponibilă mai repede odată ce analizatorul ajunge la acea secțiune de cod:

 <head> ... <link rel="preload" href="cls-inducing-javascript.js" as="script"> ... </head> <body> ... <style> .cls-inducing-div { display: none; } </style> <div class="cls-inducing-div"></div> <script src="cls-inducing-javascript.js"></script> <style> .cls-inducing-div { display: block; } </style> ... </body>

Acum, după cum am spus, acest lucru sunt sigur că îi va face pe unii oameni de performanță web să se înfioreze, deoarece sfatul este să utilizați async, defer sau mai nou type="module" (care sunt defer -ed implicit) în JavaScript în mod special pentru a evita blocarea render , în timp ce noi facem invers aici! Cu toate acestea, dacă conținutul nu poate fi predeterminat și va provoca schimbări supărătoare, atunci nu are rost să-l redați mai devreme.

Am folosit această tehnică pentru un banner cookie care s-a încărcat în partea de sus a paginii și a mutat conținutul în jos:

O captură de ecran a unei pagini web, în ​​care conținutul este deplasat în jos atunci când un banner cookie este adăugat în partea de sus a paginii.
O notificare de cookie de sus a paginii sau un alt banner poate muta conținutul în jos. (Previzualizare mare)

Acest lucru a necesitat citirea unui cookie pentru a vedea dacă se afișează sau nu bannerul cookie și, deși acesta putea fi finalizat pe partea serverului, acesta a fost un site static, fără posibilitatea de a modifica dinamic HTML-ul returnat.

Bannerele cookie pot fi implementate în diferite moduri pentru a evita CLS. De exemplu, avându-le în partea de jos a paginii sau suprapunându-le deasupra conținutului, mai degrabă decât deplasând conținutul în jos. Am preferat să păstrăm conținutul în partea de sus a paginii, așa că a trebuit să folosim această tehnică pentru a evita schimbările. Există diverse alte alerte și bannere pe care proprietarii de site-uri ar putea prefera să fie în partea de sus a paginii din diverse motive.

De asemenea, am folosit această tehnică pe o altă pagină în care JavaScript mută conținutul în coloanele „principale” și „deoparte” (din motive în care nu voi intra, nu a fost posibil să construiesc acest lucru corect pe partea serverului HTML). Ascunderea din nou a conținutului, până când JavaScript a rearanjat conținutul și abia apoi afișarea acestuia, a evitat problemele CLS care trăgeau scorul CLS al acestor pagini în jos. Și din nou conținutul este afișat automat, chiar dacă JavaScript nu rulează dintr-un motiv oarecare și este afișat conținutul neschimbat.

Folosirea acestei tehnici poate afecta alte valori (în special LCP și, de asemenea, First Contentful Paint) pe măsură ce întârziați randarea și, de asemenea, blocați preîncărcarea anticipată a browserelor, dar este un alt instrument de luat în considerare pentru acele cazuri în care nu există altă opțiune.

Concluzie

Schimbarea cumulativă a aspectului este cauzată de modificarea dimensiunilor conținutului sau de injectarea de conținut nou în pagină prin rularea târzie a JavaScript. În această postare, am discutat despre diverse sfaturi și trucuri pentru a evita acest lucru. Mă bucur că lumina reflectoarelor Core Web Vitals a strălucit asupra acestei probleme iritante - de prea mult timp noi dezvoltatorii web (și cu siguranță mă includ în asta) am ignorat această problemă.

Curățarea propriilor site-uri web a dus la o experiență mai bună pentru toți vizitatorii. Vă încurajez să vă uitați și la problemele dvs. CLS și sperăm că unele dintre aceste sfaturi vă vor fi utile atunci când o faceți. Cine știe, s-ar putea chiar să reușești să ajungi la scorul evaziv 0 CLS pentru toate paginile tale!

Mai multe resurse

  • Articole Core Web Vitals aici pe Smashing Magazine, inclusiv pe al meu despre Setarea lățimii și înălțimii pe imagini, Măsurarea valorilor vitale ale Web de bază și Descriptori de font CSS.
  • Documentația Google Core Web Vitals, inclusiv pagina lor pe CLS.
  • Mai multe detalii despre modificarea recentă la CLS și apoi această modificare a început să se actualizeze în diverse instrumente Google.
  • Jurnalul de modificări CLS care detaliază modificări în fiecare versiune de Chrome.
  • Ghidul aproape complet pentru schimbarea cumulativă a aspectului de Jess Peck.
  • Schimbarea cumulativă a aspectului: Măsurați și evitați instabilitatea vizuală de Karolina Szczur.
  • Un generator GIF Layout Shift pentru a ajuta la generarea de demonstrații care pot fi partajate ale CLS.