Отладка изменений макета

Узнайте, как выявить и исправить сдвиги макета.

Кэти Хемпениус
Katie Hempenius

В первой части этой статьи обсуждаются инструменты для отладки изменений макета, а во второй части обсуждается мыслительный процесс, который следует использовать при определении причины изменения макета.

API нестабильности макета — это механизм браузера для измерения и составления отчетов об изменениях макета. Все инструменты для отладки изменений макета, включая DevTools, в конечном итоге основаны на API нестабильности макета. Однако прямое использование Layout Instability API является мощным инструментом отладки благодаря своей гибкости.

Использование

Тот же фрагмент кода, который измеряет совокупный сдвиг макета (CLS), также может служить для отладки сдвигов макета. В приведенном ниже фрагменте информация об изменениях макета выводится на консоль. Просмотр этого журнала предоставит вам информацию о том, когда, где и как произошел сдвиг макета.

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});

При запуске этого сценария имейте в виду, что:

  • Опция buffered: true указывает, что PerformanceObserver должен проверить буфер записей производительности браузера на предмет записей производительности, которые были созданы до инициализации наблюдателя. В результате PerformanceObserver сообщит об изменениях макета, произошедших как до, так и после его инициализации. Имейте это в виду при проверке журналов консоли. Первоначальное избыток изменений макета может отражать невыполненную отчетность, а не внезапное возникновение многочисленных изменений макета.
  • Чтобы избежать влияния на производительность, PerformanceObserver ждет, пока основной поток не будет простаивать, чтобы сообщить об изменениях макета. В результате, в зависимости от того, насколько занят основной поток, может возникнуть небольшая задержка между моментом сдвига макета и его регистрацией в консоли.
  • Этот сценарий игнорирует сдвиги макета, произошедшие в течение 500 мс после ввода пользователя, и поэтому не учитываются в CLS.

Информация о сдвигах макета передается с помощью комбинации двух API: интерфейсов LayoutShift и LayoutShiftAttribution . Каждый из этих интерфейсов описан более подробно в следующих разделах.

LayoutShift

О каждом сдвиге макета сообщается с помощью интерфейса LayoutShift . Содержимое записи выглядит следующим образом:

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

Запись выше указывает на сдвиг макета, во время которого три элемента DOM изменили положение. Оценка смещения макета для этого конкретного смещения макета составила 0.175 .

Вот свойства экземпляра LayoutShift , которые наиболее важны для отладки изменений макета:

Свойство Описание
sources Свойство sources перечисляет элементы DOM, которые были перемещены во время изменения макета. Этот массив может содержать до пяти источников. В случае, если сдвиг макета затронул более пяти элементов, сообщается о пяти крупнейших (с точки зрения влияния на стабильность макета) источниках смещения макета. Эта информация передается с помощью интерфейса LayoutShiftAttribution (подробнее описано ниже).
value Свойство value сообщает оценку сдвига макета для конкретного сдвига макета.
hadRecentInput Свойство hadRecentInput указывает, произошел ли сдвиг макета в течение 500 миллисекунд после ввода пользователя.
startTime Свойство startTime указывает, когда произошел сдвиг макета. startTime указывается в миллисекундах и измеряется относительно времени начала загрузки страницы .
duration Свойство duration всегда будет установлено в 0 . Это свойство унаследовано от интерфейса PerformanceEntry (интерфейс LayoutShift расширяет интерфейс PerformanceEntry ). Однако концепция продолжительности не применяется к событиям смещения макета, поэтому для нее установлено значение 0 . Информацию об интерфейсе PerformanceEntry смотрите в спецификации .

LayoutShiftАтрибуция

Интерфейс LayoutShiftAttribution описывает один сдвиг одного элемента DOM. Если несколько элементов смещаются во время изменения макета, свойство sources содержит несколько записей.

Например, приведенный ниже JSON соответствует сдвигу макета с одним источником: сдвигу вниз элемента DOM <div id='banner'> с y: 76 на 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
      }
    }
  ]

Свойство node идентифицирует элемент HTML, который сместился. При наведении курсора на это свойство в DevTools выделяется соответствующий элемент страницы.

Свойства previousRect и currentRect сообщают размер и положение узла.

  • Координаты x и y сообщают координату x и координату y соответственно верхнего левого угла элемента.
  • Свойства width и height сообщают ширину и высоту элемента соответственно.
  • Свойства top , right , bottom и left сообщают значения координат x или y, соответствующие заданному краю элемента. Другими словами, значение top равно y ; значение bottom равно y+height .

Если все свойства previousRect установлены в 0, это означает, что элемент переместился в поле зрения. Если все свойства currentRect установлены в 0, это означает, что элемент вышел из поля зрения.

Одна из наиболее важных вещей, которую следует понимать при интерпретации этих результатов, заключается в том, что элементы, указанные в качестве источников, — это элементы, которые сместились во время изменения макета. Однако возможно, что эти элементы лишь косвенно связаны с «основной причиной» нестабильности макета. Вот несколько примеров.

Пример №1

Об этом сдвиге макета будет сообщаться с одним источником: элементом B. Однако основной причиной этого изменения макета является изменение размера элемента A.

Пример, показывающий сдвиг макета, вызванный изменением размеров элемента.

Пример №2

О сдвиге макета в этом примере будет сообщено с помощью двух источников: элемента A и элемента B. Основной причиной этого смещения макета является изменение положения элемента A.

Пример, показывающий сдвиг макета, вызванный изменением положения элемента

Пример №3

О сдвиге макета в этом примере будет сообщаться с одним источником: элементом B. Изменение положения элемента B привело к этому сдвигу макета.

Пример, показывающий сдвиг макета, вызванный изменением положения элемента

Пример №4

Хотя элемент B меняет размер, в этом примере сдвиг макета не происходит.

Пример, показывающий, как элемент меняет размер, но не вызывает сдвига макета

Посмотрите демонстрацию того, как API нестабильности макета сообщает об изменениях в DOM .

Инструменты разработчика

Панель производительности

В области «Оперативность» панели «Производительность» DevTools отображаются все изменения макета, которые происходят во время заданной трассировки производительности, даже если они происходят в течение 500 мс после взаимодействия с пользователем и, следовательно, не учитываются в CLS. При наведении курсора на определенное изменение макета на панели «Возможность» выделяется затронутый элемент DOM.

Снимок экрана со сдвигом макета, отображаемым на панели «Сеть» DevTools.

Чтобы просмотреть дополнительную информацию о сдвиге макета, нажмите на сдвиг макета, затем откройте ящик «Сводка» . Изменения размеров элемента отображаются в формате [width, height] ; изменения положения элемента перечисляются в формате [x,y] . Свойство «Недавний ввод» указывает, произошло ли изменение макета в течение 500 мс после взаимодействия с пользователем.

Снимок экрана: вкладка «Сводка» DevTools для изменения макета

Для получения информации о продолжительности смены макета откройте вкладку Журнал событий . Продолжительность сдвига макета также можно приблизительно определить, посмотрев на панели «Впечатление» длину красного прямоугольника сдвига макета.

Снимок экрана: вкладка «Журнал событий» DevTools для изменения макета

Дополнительную информацию об использовании панели «Производительность» см. в документе «Справочник по анализу производительности» .

Выделить области смещения макета

Выделение областей смещения макета может быть полезным методом для быстрого и наглядного определения местоположения и времени смещения макета, происходящего на странице.

Чтобы включить области смещения макета в DevTools, выберите «Настройки» > «Дополнительные инструменты» > «Визуализация» > «Области смещения макета», а затем обновите страницу, которую вы хотите отладить. Области смещения макета будут ненадолго выделены фиолетовым цветом.

Мыслительный процесс для выявления причины сдвигов макета

Вы можете использовать приведенные ниже шаги, чтобы определить причину смещения макета независимо от того, когда и как происходит сдвиг макета. Эти шаги можно дополнить запуском Lighthouse, однако имейте в виду, что Lighthouse может определять только изменения макета, произошедшие во время начальной загрузки страницы. Кроме того, Lighthouse также может предлагать только некоторые причины смещения макета — например, элементы изображения, которые не имеют явно заданной ширины и высоты.

Выявление причины смещения макета

Сдвиги макета могут быть вызваны следующими событиями:

  • Изменения положения элемента DOM
  • Изменения размеров элемента DOM
  • Вставка или удаление элемента DOM
  • Анимации, запускающие макет

В частности, элемент DOM, непосредственно предшествующий смещенному элементу, с наибольшей вероятностью будет вовлечен в «вызывание» сдвига макета. Таким образом, при выяснении того, почему произошел сдвиг макета, учитывайте:

  • Изменилось ли положение или размеры предыдущего элемента?
  • Был ли элемент DOM вставлен или удален перед смещенным элементом?
  • Было ли явно изменено положение сдвинутого элемента?

Если предыдущий элемент не вызвал смещение макета, продолжите поиск, рассматривая другие предыдущие и соседние элементы.

Кроме того, направление и расстояние смещения макета могут подсказать основную причину. Например, большой сдвиг вниз часто указывает на вставку элемента DOM, тогда как сдвиг макета на 1 или 2 пикселя часто указывает на применение конфликтующих стилей CSS или на загрузку и применение веб-шрифта.

Диаграмма, показывающая сдвиг макета, вызванный заменой шрифта
В этом примере замена шрифта привела к смещению элементов страницы вверх на пять пикселей.

Вот некоторые из конкретных действий, которые чаще всего вызывают события смещения макета:

Изменения положения элемента (не связанные с перемещением другого элемента)

Этот тип изменений часто является результатом:

  • Таблицы стилей, которые загружаются с опозданием или перезаписывают ранее объявленные стили.
  • Анимация и эффекты перехода.

Изменения размеров элемента

Этот тип изменений часто является результатом:

  • Таблицы стилей, которые загружаются с опозданием или перезаписывают ранее объявленные стили.
  • Изображения и iframe без атрибутов width и height , которые загружаются после визуализации их «слота».
  • Текстовые блоки без атрибутов width и height , которые меняют шрифты после визуализации текста.

Вставка или удаление элементов DOM

Часто это является результатом:

  • Вставка рекламы и других сторонних вставок.
  • Вставка баннеров, оповещений и модальных окон.
  • Бесконечная прокрутка и другие шаблоны UX, которые загружают дополнительный контент поверх существующего.

Анимации, запускающие макет

Некоторые анимационные эффекты могут вызвать срабатывание макета . Типичным примером этого является то, что элементы DOM «анимируются» путем увеличения таких свойств, как top или left вместо использования свойства transform CSS. Прочтите «Как создавать высокопроизводительную CSS-анимацию» для получения дополнительной информации.

Воспроизведение сдвигов макета

Вы не можете исправить сдвиги макета, которые не можете воспроизвести. Одна из самых простых, но наиболее эффективных вещей, которые вы можете сделать, чтобы лучше понять стабильность макета вашего сайта, — это потратить 5–10 минут на взаимодействие с вашим сайтом с целью вызвать изменения макета. При этом держите консоль открытой и используйте API нестабильности макета, чтобы сообщать об изменениях макета.

Если трудно обнаружить изменения в макете, попробуйте повторить это упражнение с разными устройствами и скоростями соединения. В частности, использование более медленной скорости соединения может облегчить выявление изменений макета. Кроме того, вы можете использовать оператор 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});

Наконец, если проблемы с макетом не воспроизводятся при разработке, рассмотрите возможность использования API нестабильности макета в сочетании с выбранным вами внешним инструментом ведения журнала, чтобы собрать больше информации об этих проблемах. Ознакомьтесь с примером кода, позволяющим отслеживать наибольший сдвинутый элемент на странице .