ТЛ;ДР
Свойство CSS overscroll-behavior
позволяет разработчикам переопределить поведение прокрутки браузера по умолчанию при переполнении при достижении верхней/нижней части содержимого. Варианты использования включают в себя отключение функции обновления по запросу на мобильных устройствах, удаление эффектов свечения чрезмерной прокрутки и резиновых полос, а также предотвращение прокрутки содержимого страницы, когда оно находится под модальным окном или наложением.
Фон
Границы прокрутки и цепочка прокрутки
Прокрутка — один из наиболее фундаментальных способов взаимодействия со страницей, но с некоторыми шаблонами UX может быть сложно справиться из-за необычного поведения браузера по умолчанию. В качестве примера возьмем ящик приложения с большим количеством элементов, которые пользователю, возможно, придется прокручивать. Когда они достигают дна, контейнер переполнения перестает прокручиваться, поскольку в нем больше нет контента для использования. Другими словами, пользователь достигает «границы прокрутки». Но обратите внимание, что произойдет, если пользователь продолжит прокрутку. Содержимое за ящиком начинает прокручиваться ! Прокрутку берет на себя родительский контейнер; сама главная страница в примере.
Оказывается, такое поведение называется цепочкой прокрутки ; поведение браузера по умолчанию при прокрутке контента. Часто значение по умолчанию довольно приятно, но иногда оно нежелательно или даже неожиданно. Некоторые приложения могут захотеть предоставить другой пользовательский интерфейс, когда пользователь достигает границы прокрутки.
Эффект обновления
«Потянуть, чтобы обновить» — это интуитивный жест, популяризированный мобильными приложениями, такими как Facebook и Twitter. Открыв ленту социальных сетей и отпустив ее, вы создадите новое пространство для загрузки более свежих публикаций. Фактически, этот конкретный UX стал настолько популярным , что мобильные браузеры, такие как Chrome на Android, переняли тот же эффект. Проведение пальцем вниз вверху страницы обновляет всю страницу:
В таких ситуациях, как Twitter PWA , возможно, имеет смысл отключить встроенное действие «тянуть для обновления». Почему? В этом приложении вы, вероятно, не захотите, чтобы пользователь случайно обновил страницу. Также есть вероятность увидеть анимацию двойного обновления! В качестве альтернативы, возможно, было бы лучше настроить действие браузера, более точно согласовав его с брендом сайта. К сожалению, этот тип настройки было сложно осуществить. В конечном итоге разработчики пишут ненужный JavaScript, добавляют непассивные прослушиватели касаний (которые блокируют прокрутку) или помещают всю страницу в <div>
100vw/vh (чтобы предотвратить переполнение страницы). Эти обходные пути имеют хорошо задокументированное негативное влияние на производительность прокрутки.
Мы можем сделать лучше!
Знакомство с overscroll-behavior
Свойство overscroll-behavior
— это новая функция CSS, которая управляет тем, что происходит при чрезмерной прокрутке контейнера (включая саму страницу). Вы можете использовать его, чтобы отменить цепочку прокрутки, отключить/настроить действие «Потянуть для обновления», отключить эффекты «резиновой ленты» в iOS (когда Safari реализует overscroll-behavior
) и многое другое. Самое приятное то, что использование overscroll-behavior
не оказывает негативного влияния на производительность страницы, как хаки, упомянутые во введении!
Свойство принимает три возможных значения:
- авто — по умолчанию. Свитки, возникающие на элементе, могут распространяться на элементы-предки.
- содержат — предотвращает цепочку прокрутки. Свитки не распространяются на предков, но отображаются локальные эффекты внутри узла. Например, эффект свечения при чрезмерной прокрутке на 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
:
Отключение обновления по запросу
Отключение действия pull-to-refresh осуществляется одной строкой 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="refresher">
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
</div>
<section id="inbox"><!-- msgs --></section>
<script>
let _startY;
const inbox = document.querySelector('#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.classList.contains('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
.