Кратко : TL;DR
Свойство CSS overscroll-behavior позволяет разработчикам переопределять поведение прокрутки по умолчанию, когда пользователь достигает верхней или нижней границы контента. Например, можно отключить функцию обновления страницы при потягивании вниз на мобильных устройствах, убрать эффекты свечения и растягивания при прокрутке за пределы страницы, а также запретить прокрутку контента страницы, когда он находится под модальным окном или оверлеем.
Фон
Границы прокрутки и цепочка прокрутки
Прокрутка – один из основных способов взаимодействия со страницей, но некоторые шаблоны UX могут быть сложными в работе из-за особенностей поведения браузера по умолчанию. В качестве примера возьмем панель приложений с большим количеством элементов, которые пользователю, возможно, придется прокручивать. Когда пользователь доходит до конца, прокрутка останавливается, потому что контент закончился. Другими словами, пользователь достигает границы прокрутки. Но обратите внимание, что происходит, если пользователь продолжает прокручивать. Начнет прокручиваться контент за боковой панелью. Прокрутка выполняется в родительском контейнере, то есть на самой странице.
Оказывается, такое поведение называется цепочкой прокрутки; поведение браузера по умолчанию при прокрутке контента. Часто значение по умолчанию вполне подходит, но иногда оно нежелательно или даже неожиданно. В некоторых приложениях может потребоваться обеспечить другой пользовательский интерфейс, когда пользователь достигает границы прокрутки.
Эффект "Потяните, чтобы обновить"
Жест "Потянуть, чтобы обновить" стал популярным благодаря таким мобильным приложениям, как Facebook и Twitter. Если потянуть вниз ленту социальной сети и отпустить, появится место для загрузки новых публикаций. На самом деле, этот конкретный UX стал настолько популярным, что мобильные браузеры, такие как Chrome на Android, приняли тот же эффект. Если провести вниз в верхней части страницы, она обновится целиком.
в Twitter при обновлении ленты в PWA.
обновляет всю страницу.
В некоторых случаях, например в PWA Twitter, может быть целесообразно отключить встроенное действие "Потянуть, чтобы обновить". Почему? В этом приложении вы, вероятно, не хотите, чтобы пользователь случайно обновил страницу. Также есть вероятность увидеть двойную анимацию обновления. В качестве альтернативы может быть лучше настроить действие браузера, более точно согласовав его с брендингом сайта. К сожалению, такую настройку сложно реализовать. Разработчикам приходится писать ненужный код JavaScript, добавлять непассивные прослушиватели касаний (которые блокируют прокрутку) или помещать всю страницу в контейнер <div> размером 100vw/vh (чтобы предотвратить переполнение страницы). Эти обходные пути имеют хорошо задокументированные негативные последствия для производительности прокрутки.
Мы можем лучше!
Представляем overscroll-behavior
Свойство overscroll-behavior – это новая функция CSS, которая управляет поведением контейнера (включая саму страницу) при прокрутке за его пределы. С его помощью можно отменить цепочку прокрутки, отключить или настроить действие "потянуть, чтобы обновить", отключить эффект резиновой ленты в iOS (когда Safari реализует overscroll-behavior) и многое другое.
Самое главное, что использование overscroll-behavior не влияет на скорость загрузки страницы, в отличие от хаков, упомянутых во введении.
Свойство может принимать три значения:
- auto – значение по умолчанию. Прокрутка, которая начинается на элементе, может распространяться на родительские элементы.
- contain – предотвращает цепочку прокрутки. Прокрутка не распространяется на предков, но локальные эффекты в узле отображаются. Например, эффект свечения при прокрутке на Android или эффект резиновой ленты на iOS, который уведомляет пользователя, когда он достиг границы прокрутки. Примечание. Использование
overscroll-behavior: containв элементеhtmlпредотвращает навигацию при прокрутке за пределы страницы. - none – то же, что и
contain, но также предотвращает эффекты достижения конца прокрутки внутри самого узла (например, свечение при достижении конца прокрутки в Android или эффект резиновой ленты в iOS).
Давайте рассмотрим несколько примеров использования overscroll-behavior.
Как предотвратить прокрутку за пределы элемента с фиксированной позицией
Сценарий с окном чата
Представьте, что в нижней части страницы есть окно чата с фиксированным положением. Предполагается, что окно чата является автономным компонентом и прокручивается отдельно от контента за ним. Однако из-за цепочки прокрутки документ начинает прокручиваться, как только пользователь попадает на последнее сообщение в истории чата.
Для этого приложения больше подходит, чтобы прокрутка, начатая в окне чата, оставалась в нем. Для этого добавим overscroll-behavior: contain к элементу, содержащему сообщения чата:
#chat .msgs {
overflow: auto;
overscroll-behavior: contain;
height: 300px;
}
По сути, мы создаем логическое разделение между контекстом прокрутки окна чата и основной страницей. В результате основная страница остается на месте, когда пользователь достигает верхней или нижней части истории чата. Прокрутка, начатая в окне чата, не распространяется за его пределы.
Сценарий с оверлеем на странице
Другой вариант сценария "прокрутка под контентом" – когда контент прокручивается под оверлеем с фиксированной позицией. Пора устроить
overscroll-behavior! Браузер пытается помочь, но в итоге сайт выглядит так, будто в нем есть ошибки.
Пример – модальное окно с атрибутом overscroll-behavior: contain и без него:
Как отключить обновление страницы при потягивании вниз
Отключить обновление страницы при перетаскивании можно с помощью одной строки CSS. Просто предотвратите цепочку прокрутки на всем элементе, определяющем область просмотра. В большинстве случаев это <html> или <body>:
body {
/* Disables pull-to-refresh but allows overscroll glow effects. */
overscroll-behavior-y: contain;
}
Это простое дополнение позволяет исправить двойную анимацию обновления в демо-версии чата и вместо этого реализовать пользовательский эффект с более аккуратной анимацией загрузки. При обновлении папки "Входящие" она размывается.
Вот фрагмент полного кода:
<style>
body.refreshing #inbox {
filter: blur(1px);
touch-action: none; /* prevent scrolling */
}
body.refreshing .refresher {
transform: translate3d(0,150%,0) scale(1);
z-index: 1;
}
.refresher {
--refresh-width: 55px;
pointer-events: none;
width: var(--refresh-width);
height: var(--refresh-width);
border-radius: 50%;
position: absolute;
transition: all 300ms cubic-bezier(0,0,0.2,1);
will-change: transform, opacity;
...
}
</style>
<div class="refre>she<r"
div class=&qu><ot;l>oad<ing-bar"/div
div>< cla>ss=<"loading-bar"></div>
<div class="loading><-bar>&<quot>;/<div
div class=&q><uot;loading><-bar&quo>t;</div
/>div
section id="inbox"!-- msgs --/section
script
let _startY;
const inbox = document.querySel>ector('#inbox');
inbox.addEventListener('touchstart', e = {
_startY = e.touches>[0].pageY;
}, {passive: true});
inbox.addEventListener('touchmove', e = {
const y = e.touches[0].pageY;
// Activate custom pull-to-refresh effects when at the top of the container&&
> // and &&user is scrolling up.
if (document.scrollingElement.scrollTop === 0 y _startY
!document.body.class<List.co>ntains('refreshing')) {
// refresh inbox.
}
}, {passive: true});
/script
Как отключить свечение и эффект растягивания при достижении конца прокрутки
Чтобы отключить эффект отскока при достижении границы прокрутки, используйте overscroll-behavior-y: none:
body {
/* Disables pull-to-refresh and overscroll glow effect.
Still keeps swipe navigations. */
overscroll-behavior-y: none;
}
Полная демоверсия
В демоверсии чата overscroll-behavior используется для создания анимации обновления и предотвращения прокрутки за пределами виджета чата. Это обеспечивает оптимальное удобство для пользователей, которого было бы сложно достичь без CSS.overscroll-behavior