Отладка ошибок в скролл-контейнере и фиксированных заголовках

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

Распространенные ошибки:

  1. Не скролится контент;
  2. Не скролится или не отображается скроллбар;
  3. Скролбар отображается, но при скроллировании уезжает за пределы экрана, или наоборот, после того как доскролили до края, скролбар еще не прижался к этому краю;
  4. Неправильно отображаются тени;
  5. Некорректно фиксируются заголовки;
  6. Бесконечно загружается контент в списке.

Как правило, источником проблем является неправильная настройка размеров контейнера.

Условия корректной работы скролл-контейнера

Чтобы избежать описанных выше ошибок, необходимо учитывать следующие нюансы:

  1. Должен быть задан размер скролл-контейнера. Это можно сделать явно с помощью стиля height, либо используя другие средства css, например flexbox.
  2. Cкролл-контейнер должен умещаться в видимой области экрана.
  3. Чтобы отображался скоролл, необходимо задать для детей скролл-контейнера размер больший чем у самого скролл-контейнера.
  4. Если размеры и видимость области меняется прикладными средствами, то об этом необходимо оповестить внутренние и внешние контролы. Например, область скрывается или отображается с помощью добавления класса ws-hidden. В таком случае необходимо оповестить внутренние и внешние контролы с помощью механизма авторазмеров. Подробнее читайте здесь.

Алгоритм поиска ошибок

Рис. 1 Правильно.


Рис. 2 Неправильно.

  • 1. Найдите скролл-контейнер в котором ожидается скороллирование. Скролл-контейнер можно найти по классу controls-Scroll-Container. На странице могут быть другие скролл-контейнеры ближе к корню страницы.
  • 2. Проверьте размер скролл-контейнера. Он должен полностью помещаться на странице и не обрезаться родительскими контейнерами.
    • 2.1 Если в пункте 2 обнаружена проблема, то обойдите DOM-дерево начиная с body.
    • 2.2 Проверьте чему равна высота текущего элемента.
    • 2.3 Суммируйте высоты дочерних элементов, которые лежат в потоке верстки.
    • 2.4 Если высота родительского блока не равна сумме высот дочерних, то источником проблемы является один из дочерних блоков. Настройте высоты детей, так чтобы их сумма была равна высоте родительского блока.
      • 2.4.1 Проверьте высоту скролл-контейнера, если она все еще не правильная, то вернитесь к шагу 2.2.
    • 2.5 Если высота родительского блока равна сумме высот дочерних, выберите дочерний элемент, который лежит в ветке ведущей к скролл-контейнеру и венитесь к пункту 2.2.
  • 3. Проверьте размер контента скролл-контейнера. Прикладной контент лежит в контейнере controls-Scroll-ContainerBase. Размер всех детей controls-Scroll-ContainerBase должен быть больше самого controls-Scroll-ContainerBase.

Если это не так, то уберите лишние стили с контента. Часто параметр height: 100% или flex-shrink: 1. Такого не должно быть, за исключением случаев когда это сделано намерено, чтобы отключить скроллирование в скролл-контейнере.

Важно

Для правильного распространения размеров по верстке используйте верстку через flexbox. Подробнее читайте здесь.

Типовые ошибки

Скролл-контейнер внутри другого скролл-контейнера

Рис. 3 Скролл-контейнер внутри другого скролл-контейнера.

Сценарий: Внутри внешнего скролл-контейнера может быть расположено несколько вложенных. Если для внешнего скролл-контейнера на контенте установлен размер 100%, то необходимо четко понимать в каких вложенных контейнерах необходимо поддержать скролл.

Избегайте таких сценариев. Если возникла крайняя необходимость в данном сценарии, то проконсультируйтесь с А. Ю. Мироновым. Также, часто возникают случаи, когда меняют верстку и не замечают что контент начинает скроллироваться во внешнем скролл-контейнере, а не во внутреннем.

К данным ошибкам могут приводить особенности некоторых браузеров.

Проверяем корректность управления размерами и видимостью областей

Сценарий: Изменились размеры контента, а скролл-контейнер никак не отреагировал. Не обновились размеры скролбара, не исчезли или не появились тени.

Проблема скорее всего в том, что скролл-контейнер не оповещен об изменениях. Проверьте это установив точку остановки в метод _controlResizeHandler в контроле Сontrols/scroll:Container.

Рис. 4 Пример точки остановки.

Если мы не попадаем в этот метод, то это значит что тот кто изменил верстку не оповестил остальных что на странице поменялись размеры.

Необходимо оповещать внутренние и внешние контролы об изменении размеров если они меняются из-за:

  1. Добавление/удаление контента в результате работы конструкции <ws:if …>
  2. Добавление удаление стиля display: none или класса ws-hidden
  3. Добавление/удаление других стилей влияющих на размеры элементов верстке.

Подробнее читайте здесь.

Платформенные компоненты реагируют на изменение своих размеров и оповещают об их изменении. Например, список генерирует событие controlResize когда дорисовывает данные. Вкладки и переключаемые области оповещают своих детей после того, как отобразили их.

Важно

Оповещать об изменении размеров надо после того, как эти изменения были применены к DOM-дереву, т.е. в хуке жизненного цикла _afterUpdate. Подробнее о хуках жизненного цикла контрола читайте здесь.

Другие известные типы ошибок фиксированных заголовков

Дергаются заголовки при скроллировании

Проблема носит комплексный характер. Вероятно во время скроллирования происходит обновление верстки контрола с тяжелыми расчетами на js. Снимите профиль во время скроллирования. Если есть js фреймы продолжительностью более 300-500 мс, то необходимо провести оптимизацию.

Дергаются заголовки на Edge и iPad при скроллировании

Иногда проблема может быть в стилях родительских контролов. В этом случае если установить на скроллируемый контейнер или на заголовки transform: translateZ(0);, то проблема полностью или частично уходит.

Важно

Рекомендуется найти стили, которые вызывают проблему и попробовать избавиться от них.

Не фиксируются заголовки

Заголовки могут не фиксироваться если между заголовками и скролл-контейнером установлен стиль overflow.

Рис. 5 Установлен стиль overflow.

Заголовки фиксируются только в рамках ближайшего скроллируемого контейнера. Если есть несколько вложенных скроллируемых областей, и скроллирование происходит не в ближайшей области от заголовка, то он не будет фиксироваться.

Рис. 6 Заголовок фиксируюется только в рамках ближайшего скроллируемого контейнера.