Debuguj przesunięcia układu

Dowiedz się, jak wykrywać i naprawiać przesunięcia układu.

Katie Hempenius
Katie Hempenius

Pierwsza część tego artykułu omawia narzędzia do debugowania zmian układu, a druga – proces myślenia, którego należy użyć do określenia przyczyny zmiany układu.

Narzędzia

Interfejs Layout Instability API

Layout Instability API to mechanizm przeglądarki do pomiaru i raportowania zmian układu. Wszystkie narzędzia do debugowania przesunięć układu, w tym DevTools, są ostatecznie oparte na interfejsie Layout Instability API. Bezpośrednie używanie interfejsu Layout Instability API jest jednak zaawansowanym narzędziem do debugowania ze względu na swoją elastyczność.

Wykorzystanie

Ten sam kod fragmentu kodu, który mierzy skumulowane przesunięcie układu (CLS), może też służyć do debugowania przesunięć układu. Fragment kodu poniżej zapisuje w konsoli informacje o przesunięciu układu. Dzięki temu dowiesz się, kiedy, gdzie i jak nastąpiła zmiana układu.

let cls = 0;
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

Podczas uruchamiania tego skryptu pamiętaj, że:

  • Opcja buffered: true wskazuje, że PerformanceObserver powinien sprawdzić bufor wpisu wydajności przeglądarki pod kątem wpisów dotyczących wydajności, które zostały utworzone przed inicjowaniem obserwatora. W efekcie PerformanceObserver będzie raportować przesunięcia układu, które wystąpiły zarówno przed, jak i po jego zainicjowaniu. Pamiętaj o tym, gdy sprawdzasz logi konsoli. Początkowa porcja przesunięć układu może odzwierciedlić zaległości raportowania, a nie nagłe wystąpienie licznych przesunięć układu.
  • Aby uniknąć wpływu na wydajność, funkcja PerformanceObserver czeka, aż główny wątek będzie bezczynny, aby przekazać informacje o zmianach układu. W zależności od obciążenia wątku głównego może wystąpić niewielkie opóźnienie między wystąpieniem zmiany układu a jej zarejestrowaniem w konsoli.
  • Ten skrypt ignoruje zmiany układu, które nastąpiły w ciągu 500 ms od wprowadzenia danych przez użytkownika, i dlatego nie są wliczane do wartości CLS.

Informacje o zmianach układu są raportowane za pomocą kombinacji 2 interfejsów API: LayoutShift i LayoutShiftAttribution. W następnych sekcjach znajdziesz więcej informacji o każdym z tych interfejsów.

LayoutShift

Każde przesunięcie układu jest raportowane w interfejsie LayoutShift. Zawartość wpisu wygląda tak:

duration: 0
entryType: "layout-shift"
hadRecentInput: false
lastInputTime: 0
name: ""
sources: (3) [LayoutShiftAttribution, LayoutShiftAttribution, LayoutShiftAttribution]
startTime: 11317.934999999125
value: 0.17508567530168798

Powyższy wpis wskazuje zmianę układu, podczas której 3 elementy DOM zmieniły położenie. Wynik przesunięcia układu w przypadku tego konkretnego przesunięcia układu wyniósł 0.175.

Oto właściwości instancji LayoutShift, które najlepiej nadają się do debugowania przesunięć układu:

Właściwość Opis
sources Właściwość sources zawiera listę elementów DOM, które zostały przeniesione podczas zmiany układu. Ta tablica może zawierać maksymalnie 5 źródeł. Jeśli przesunięcie układu ma wpływ na więcej niż 5 elementów, w raportach pojawia się 5 największych źródeł (mierzonych na podstawie wpływu na stabilność układu). Te informacje są raportowane za pomocą interfejsu LayoutShiftAttribution (zostało to szczegółowo opisane poniżej).
value Usługa value raportuje wynik przesunięcia układu dla konkretnego przesunięcia układu.
hadRecentInput Właściwość hadRecentInput wskazuje, czy przesunięcie układu nastąpiło w ciągu 500 milisekund od wprowadzenia danych przez użytkownika.
startTime Właściwość startTime wskazuje, kiedy wystąpiło przesunięcie układu. Wartość startTime jest podawana w milisekundach i mierzona względem czasu zainicjowania wczytywania strony.
duration Właściwość duration będzie zawsze mieć wartość 0. Ta właściwość jest dziedziczona z interfejsu PerformanceEntry (interfejs LayoutShift rozszerza interfejs PerformanceEntry). Czas trwania nie dotyczy jednak zdarzeń przesunięcia układu, więc ma wartość 0. Informacje o interfejsie PerformanceEntry znajdziesz w specyfikacji.

LayoutShiftAttribution

Interfejs LayoutShiftAttribution opisuje pojedynczy przesunięcie pojedynczego elementu DOM. Jeśli podczas przesunięcia układu przesuwa się wiele elementów, właściwość sources zawiera wiele wpisów.

Na przykład poniższy plik JSON odpowiada przesunięciem układu z jednym źródłem: przesunięciem elementu DOM <div id='banner'> w dół z y: 76 na y:246.

// ...
  "sources": [
    {
      "node": "div#banner",
      "previousRect": {
        "x": 311,
        "y": 76,
        "width": 4,
        "height": 18,
        "top": 76,
        "right": 315,
        "bottom": 94,
        "left": 311
      },
      "currentRect": {
        "x": 311,
        "y": 246,
        "width": 4,
        "height": 18,
        "top": 246,
        "right": 315,
        "bottom": 264,
        "left": 311
      }
    }
  ]

Właściwość node identyfikuje element HTML, który został przesunięty. Najechanie kursorem na tę właściwość w Narzędziach deweloperskich podświetla odpowiadający element strony.

Właściwości previousRect i currentRect raportują rozmiar i pozycję węzła.

  • Współrzędne x i y określają współrzędne X i Y odpowiednio do lewego górnego rogu elementu.
  • Właściwości width i height podają odpowiednio szerokość i wysokość elementu.
  • Właściwości top, right, bottom i left zgłaszają wartości współrzędnych x i y odpowiadające danej krawędzi elementu. Innymi słowy, wartość top jest równa y, a wartość bottom jest równa y+height.

Jeśli wszystkie właściwości obiektu previousRect mają wartość 0, element przesunął się w widok. Jeśli wszystkie właściwości elementu currentRect mają wartość 0, oznacza to, że element jest poza widokiem.

Najważniejsze, co należy wiedzieć podczas interpretowania tych danych wyjściowych, to fakt, że elementy wymienione jako źródła to elementy, które zostały przesunięte podczas zmiany układu. Możliwe jednak, że te elementy są tylko pośrednio powiązane z „główną przyczyną” niestabilności układu. Oto kilka przykładów:

Przykład 1

Ta zmiana układu zostałaby zgłoszona z jednego źródła: elementu B. Główną przyczyną tego przesunięcia układu jest jednak zmiana rozmiaru elementu A.

Przykład przedstawiający przesunięcie układu spowodowane zmianą wymiarów elementu

Przykład 2

W tym przykładzie przesunięcie układu zostałoby odnotowane w 2 źródłach: elemencie A i elemencie B. Główną przyczyną tego przesunięcia układu jest zmiana położenia elementu A.

Przykład przedstawiający przesunięcie układu spowodowane zmianą pozycji elementu

Przykład 3

W tym przykładzie przesunięcie układu zostałoby odnotowane z 1 źródłem: elementem B. Zmiana pozycji elementu B spowodowała przesunięcie układu.

Przykład pokazujący zmianę układu spowodowaną zmianą pozycji elementu

Przykład 4

Chociaż element B zmienia rozmiar, w tym przykładzie nie ma przesunięcia układu.

Przykład elementu, który zmienia rozmiar, ale nie powoduje zmiany układu

Obejrzyj prezentację, jak zmiany DOM są zgłaszane przez interfejs API niestabilności układu.

Narzędzia deweloperskie

Panel wydajności

W panelu Wrażenia w DevTools w panelu Wydajność są wyświetlane wszystkie przesunięcia układu, które występują podczas danego śledzenia wydajności, nawet jeśli występują w ciągu 500 ms od interakcji użytkownika i dlatego nie są uwzględniane w wyrażeniu CLS. Najechanie kursorem na określone przesunięcie układu w panelu Eksperymenty powoduje podświetlenie elementu DOM, którego dotyczy ten problem.

Zrzut ekranu przedstawiający przesunięcie układu wyświetlane w panelu Sieć w Narzędziach deweloperskich

Aby wyświetlić więcej informacji o przesunięciu układu, kliknij to przesunięcie, a potem otwórz panel Podsumowanie. Zmiany wymiarów elementu są wyświetlane w formacie [width, height], a zmiany jego pozycji – w formacie [x,y]. Właściwość Ostatnie dane wejściowe wskazuje, czy zmiana układu nastąpiła w ciągu 500 ms od interakcji użytkownika.

Zrzut ekranu z kartą „Podsumowanie” w Narzędziach dla programistów w przypadku przesunięcia układu

Informacje o czasie trwania przesunięcia układu znajdziesz na karcie Dziennik zdarzeń. Czas trwania zmiany układu można też oszacować, sprawdzając w panelu Doświadczenie długość czerwonego prostokąta zmiany układu.

Zrzut ekranu przedstawiający kartę „Dziennik zdarzeń” w Narzędziach deweloperskich z przesunięciem układu

Więcej informacji o korzystaniu z panelu Skuteczność znajdziesz w artykule z informacjami o analizie skuteczności.

Podświetlanie regionów przesunięcia układu

Podświetlanie regionów przesunięcia układu może być przydatną techniką, która pozwala szybko i na pierwszy rzut oka określić lokalizację i czas przesunięcia układu na stronie.

Aby włączyć Regiony przesunięcia układu w Narzędziach deweloperskich, kliknij Ustawienia > Więcej narzędzi > Renderowanie > Regiony przesunięcia układu, a następnie odśwież stronę, którą chcesz debugować. Obszary przesunięcia układu są krótko podświetlone na fioletowo.

Proces myślenia przy identyfikowaniu przyczyny przesunięć układu

Możesz skorzystać z podanych niżej czynności, aby zidentyfikować przyczynę przesunięć układu niezależnie od tego, kiedy i w jaki sposób ma ono miejsce. Te kroki można uzupełnić uruchomieniem Lighthouse, ale pamiętaj, że Lighthouse tylko rozpoznaje zmiany układu, które wystąpiły podczas wstępnego wczytywania strony. Ponadto Lighthouse może podać sugestie tylko w przypadku niektórych przyczyn zmian układu, np. elementów obrazu, które nie mają wyraźnej szerokości ani wysokości.

Identyfikowanie przyczyny przesunięcia układu

Przesunięcia układu mogą być spowodowane tymi zdarzeniami:

  • Zmiany pozycji elementu DOM
  • Zmiany wymiarów elementu DOM
  • wstawianie lub usuwanie elementu DOM;
  • Animacje, które wywołują układ

W szczególności element DOM bezpośrednio poprzedzający przesunięty element jest elementem, który najprawdopodobniej „spowodował” przesunięcie układu. Dlatego podczas sprawdzania, dlaczego doszło do przesunięcia układu, weź pod uwagę:

  • Czy zmieniły się położenie lub wymiary poprzedniego elementu?
  • Czy przed przesuniętym elementem został wstawiony lub usunięty element DOM?
  • Czy pozycja przesuniętego elementu została zmieniona?

Jeśli poprzedni element nie spowodował zmiany układu, kontynuuj wyszukiwanie, biorąc pod uwagę inne poprzednie elementy i elementy znajdujące się w pobliżu.

Poza tym kierunek i odległość przesunięcia układu mogą dostarczyć wskazówek dotyczących głównej przyczyny. Na przykład duże przesunięcie w dół często oznacza wstawienie elementu DOM, a przesunięcie układu o 1 lub 2 piksele często wskazuje na zastosowanie sprzecznych stylów CSS lub wczytanie i zastosowanie czcionki internetowej.

Diagram przedstawiający przesunięcie układu spowodowane zmianą czcionki
W tym przykładzie zamiana czcionki spowodowała przesunięcie elementów strony w górę o 5 pikseli.

Oto niektóre z działań, które najczęściej powodują przesunięcia układu:

zmiany pozycji elementu (które nie są spowodowane ruchem innego elementu);

Ten typ zmiany jest często spowodowany:

  • Arkusze stylów, które są wczytywane późno lub zastępują wcześniej zadeklarowane style.
  • Efekty animacji i przejść.

zmiany wymiarów elementu,

Taka zmiana ma często następujące przyczyny:

  • Arkusze stylów, które są ładowane późno lub zastępują wcześniej zadeklarowane style.
  • obrazy i ramki iframe bez atrybutów widthheight, które są renderowane po wyświetleniu ich „miejsca”;
  • Bloki tekstowe bez atrybutów width ani height, które zamieniają czcionki po renderowaniu tekstu.

wstawianie lub usuwanie elementów DOM;

Zazwyczaj jest to spowodowane:

  • Wstawianie reklam i innych elementów zewnętrznych.
  • Wstawienie banerów, alertów i modałów.
  • Nieskończone przewijanie i inne wzorce UX, które wczytują dodatkowe treści powyżej istniejących treści.

Animacje, które aktywują układ

Niektóre efekty animacji mogą uruchamiać układ. Typowym przykładem jest „animowanie” elementów DOM przez zwiększanie wartości właściwości takich jak top lub left zamiast używania właściwości transform w CSS. Więcej informacji znajdziesz w artykule Jak tworzyć skuteczne animacje CSS.

Odtwarzanie przesunięć układu

Nie możesz naprawić przesunięć układu, których nie możesz odtworzyć. Jednym z najprostszych, ale najskuteczniejszych sposobów na uzyskanie lepszej stabilności układu witryny jest poświęcenie 5–10 minut na interakcję z witryną i cel powodujący jej zmiany układu. Podczas wykonywania tych czynności pozostaw konsolę otwartą i korzystaj z interfejsu Layout Instability API, aby generować raporty o przesunięciach układu.

Jeśli trudno jest znaleźć zmiany układu, rozważ powtórzenie tego ćwiczenia z różnymi urządzeniami i o różnej prędkości połączenia. W szczególności wolniejsze połączenie ułatwia wykrywanie zmian układu. Aby ułatwić sobie przechodzenie przez zmiany układu, możesz też użyć instrukcji debugger.

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      debugger;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

W przypadku problemów z układem, których nie da się odtworzyć w trakcie programowania, rozważ użycie interfejsu Layout Instability API w połączeniu z wybranym narzędziem do logowania interfejsu, aby zebrać więcej informacji o tych problemach. Sprawdź przykład kodu, który pozwala śledzić największy przesunięty element na stronie.