Отладка ошибок в скролл-контейнере и фиксированных заголовках
В данной статье рассмотрены типовые проблемы при настройке скроллируемых областей и прилипающих заголовков.
Распространенные ошибки:
- Не скролится контент;
- Не скролится или не отображается скроллбар;
- Скролбар отображается, но при скроллировании уезжает за пределы экрана, или наоборот, после того как доскролили до края, скролбар еще не прижался к этому краю;
- Неправильно отображаются тени;
- Некорректно фиксируются заголовки;
- Бесконечно загружается контент в списке.
Как правило, источником проблем является неправильная настройка размеров контейнера.
Условия корректной работы скролл-контейнера
Чтобы избежать описанных выше ошибок, необходимо учитывать следующие нюансы:
- Должен быть задан размер скролл-контейнера. Это можно сделать явно с помощью стиля height, либо используя другие средства css, например flexbox.
- Cкролл-контейнер должен умещаться в видимой области экрана.
- Чтобы отображался скоролл, необходимо задать для детей скролл-контейнера размер больший чем у самого скролл-контейнера.
- Если размеры и видимость области меняется прикладными средствами, то об этом необходимо оповестить внутренние и внешние контролы. Например, область скрывается или отображается с помощью добавления класса 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 Пример точки остановки.
Если мы не попадаем в этот метод, то это значит что тот кто изменил верстку не оповестил остальных что на странице поменялись размеры.
Необходимо оповещать внутренние и внешние контролы об изменении размеров если они меняются из-за:
- Добавление/удаление контента в результате работы конструкции <ws:if …>
- Добавление удаление стиля display: none или класса ws-hidden
- Добавление/удаление других стилей влияющих на размеры элементов верстке.
Подробнее читайте здесь.
Платформенные компоненты реагируют на изменение своих размеров и оповещают об их изменении. Например, список генерирует событие controlResize когда дорисовывает данные. Вкладки и переключаемые области оповещают своих детей после того, как отобразили их.
Важно
Оповещать об изменении размеров надо после того, как эти изменения были применены к DOM-дереву, т.е. в хуке жизненного цикла _afterUpdate. Подробнее о хуках жизненного цикла контрола читайте здесь.
Другие известные типы ошибок фиксированных заголовков
Дергаются заголовки при скроллировании
Проблема носит комплексный характер. Вероятно во время скроллирования происходит обновление верстки контрола с тяжелыми расчетами на js. Снимите профиль во время скроллирования. Если есть js фреймы продолжительностью более 300-500 мс, то необходимо провести оптимизацию.
Дергаются заголовки на Edge и iPad при скроллировании
Иногда проблема может быть в стилях родительских контролов. В этом случае если установить на скроллируемый контейнер или на заголовки transform: translateZ(0);, то проблема полностью или частично уходит.
Важно
Рекомендуется найти стили, которые вызывают проблему и попробовать избавиться от них.
Не фиксируются заголовки
Заголовки могут не фиксироваться если между заголовками и скролл-контейнером установлен стиль overflow.
Рис. 5 Установлен стиль overflow.
Заголовки фиксируются только в рамках ближайшего скроллируемого контейнера. Если есть несколько вложенных скроллируемых областей, и скроллирование происходит не в ближайшей области от заголовка, то он не будет фиксироваться.
Рис. 6 Заголовок фиксируюется только в рамках ближайшего скроллируемого контейнера.