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

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

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

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

Оснастка

API нестабильности макета

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 нестабильности макета в сочетании с выбранным вами внешним инструментом ведения журнала, чтобы собрать больше информации об этих проблемах. Ознакомьтесь с примером кода, позволяющим отслеживать наибольший сдвинутый элемент на странице .