Прокрутка на ваших сайтах

Опубликовано: 2022-03-10
Краткое резюме ↬ В этой статье описывается эффект отскока прокрутки и то, как он работает в разных веб-браузерах. Он содержит обзоры нескольких различных решений, предлагаемых в Интернете, которые можно использовать для предотвращения подпрыгивания прокрутки. В этой статье также описано свойство CSS overscroll-behavior , реализованное в Chrome в декабре 2017 года и в Firefox в марте 2018 года. Хорошее понимание этого эффекта очень полезно для создания или проектирования любого веб-сайта с фиксированными элементами.

Отскок прокрутки (также иногда называемый «резиновой полосой прокрутки» или «эластичной прокруткой») часто используется для обозначения эффекта, который вы видите, когда прокручиваете до самого верха страницы или HTML-элемента или до конца. страница или элемент на устройстве с сенсорным экраном или трекпадом, и на мгновение можно увидеть пустое пространство, прежде чем элемент или страница отскочит и выровняется обратно по своему верху / низу (когда вы отпускаете касание / пальцы). Вы можете увидеть аналогичный эффект при прокрутке CSS между элементами.

Однако в этой статье основное внимание уделяется подпрыгиванию прокрутки при прокрутке до самого верха или самого низа веб-страницы. Другими словами, когда порт прокрутки достиг своей границы прокрутки.

Сбор данных, мощный способ

Знаете ли вы, что CSS можно использовать для сбора статистики? Действительно, существует даже подход, основанный только на CSS, для отслеживания взаимодействий с пользовательским интерфейсом с помощью Google Analytics. Читать статью по теме →

Хорошее понимание отскока прокрутки очень полезно, так как это поможет вам решить, как вы создаете свои веб-сайты и как вы хотите, чтобы страница прокручивалась.

Отскок прокрутки нежелателен, если вы не хотите, чтобы fixed элементы перемещались по странице. Некоторые примеры включают в себя: когда вы хотите, чтобы верхний или нижний колонтитул был зафиксирован в определенной позиции, или если вы хотите, чтобы любой другой элемент, такой как меню, был фиксированным, или если вы хотите, чтобы страница прокручивалась в определенных позициях при прокрутке и вы не хотите, чтобы какая-либо дополнительная прокрутка происходила в самом верху или внизу страницы, что могло бы запутать посетителей вашего сайта. В этой статье будут предложены некоторые решения проблем, возникающих при работе с подпрыгиванием прокрутки в самом верху или внизу веб-страницы.

Еще после прыжка! Продолжить чтение ниже ↓

Моя первая встреча с эффектом

Впервые я заметил этот эффект, когда обновлял веб-сайт, который создал давным-давно. Вы можете просмотреть веб-сайт здесь. Нижний колонтитул внизу страницы должен был быть зафиксирован на своем месте внизу страницы и вообще не двигаться. В то же время вы должны были иметь возможность прокручивать вверх и вниз основное содержимое страницы. В идеале это должно работать так:

Подпрыгивание прокрутки в Firefox на macOS
Подпрыгивание прокрутки в Firefox на macOS. (Большой превью)

В настоящее время он работает таким образом в Firefox или в любом браузере на устройстве без сенсорного экрана или трекпада. Однако в то время я использовал Chrome на MacBook. Я прокручивал страницу вниз с помощью трекпада, когда обнаружил, что мой сайт работает неправильно. Вы можете увидеть, что произошло здесь:

Прокрутка подпрыгивает в Chrome на macOS
Подпрыгивание прокрутки в Chrome на macOS. (Большой превью)

о нет! Это не то, что должно было случиться! Я установил положение нижнего колонтитула в нижней части страницы, установив его свойство position CSS со значением fixed . Это также хорошее время, чтобы пересмотреть, что position: fixed; является. Согласно Спецификации CSS 2.1, когда «коробка» (в данном случае темно-синий нижний колонтитул) зафиксирована, она «фиксируется по отношению к области просмотра и не перемещается при прокрутке». Это означает, что нижний колонтитул не должен двигаться, когда вы прокручиваете страницу вверх и вниз. Именно это меня обеспокоило, когда я увидел, что происходит в Chrome.

Чтобы сделать эту статью более полной, ниже я покажу вам, как прокручивается страница в Mobile Edge, Mobile Safari и Desktop Safari. Это отличается от того, что происходит при прокрутке в Firefox и Chrome. Я надеюсь, что это поможет вам лучше понять, как один и тот же код в настоящее время работает по-разному. В настоящее время сложно разработать прокрутку, которая работает одинаково в разных веб-браузерах.

Подпрыгивание прокрутки в Safari на macOS. Аналогичный эффект можно увидеть для Edge и Safari на iOS.
Подпрыгивание прокрутки в Safari на macOS. Аналогичный эффект можно увидеть для Edge и Safari на iOS. (Большой превью)

Поиск решения

Одной из моих первых мыслей было то, что будет простой и быстрый способ решить эту проблему во всех браузерах. Это означает, что я думал, что смогу найти решение, которое займет несколько строк кода CSS и не будет задействован JavaScript. Поэтому одним из первых вещей, которые я сделал, была попытка добиться этого. Браузеры, которые я использовал для тестирования, включали Chrome, Firefox и Safari на macOS и Windows 10, а также Edge и Safari на iOS. Версии этих браузеров были последними на момент написания статьи (2018 год).

Решения только для HTML и CSS

Абсолютное и относительное позиционирование

Одной из первых вещей, которые я попробовал, было использование абсолютного и относительного позиционирования для позиционирования нижнего колонтитула, потому что я привык создавать такие нижние колонтитулы. Идея заключалась бы в том, чтобы установить мою веб-страницу на 100% высоты, чтобы нижний колонтитул всегда находился внизу страницы с фиксированной высотой, в то время как содержимое занимало 100% минус высота нижнего колонтитула, и вы можете прокручивать это. В качестве альтернативы вы можете установить padding-bottom вместо использования calc и установить высоту body-container на 100%, чтобы содержимое приложения не перекрывалось с нижним колонтитулом. Код CSS выглядел примерно так:

 html { width: 100%; height: 100%; overflow: hidden; position: relative; } body { width: 100%; margin: 0; font-family: sans-serif; height: 100%; overflow: hidden; } .body-container { height: calc(100% - 100px); overflow: auto; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: absolute; bottom: 0; height: 100px; width: 100%; }

Это решение работает почти так же, как исходное решение (которое было просто position: fixed; ). Одним из преимуществ этого решения по сравнению с этим является то, что прокрутка не для всей страницы, а только для содержимого страницы без нижнего колонтитула. Самая большая проблема с этим методом заключается в том, что в Mobile Safari и нижний колонтитул, и содержимое приложения перемещаются одновременно. Это делает этот подход очень проблематичным при быстрой прокрутке:

Абсолютное и относительное позиционирование
Абсолютное и относительное позиционирование.

Еще один эффект, которого я не хотел, поначалу было трудно заметить, и я понял, что это происходит только после того, как попробовал больше решений. Это заключалось в том, что прокрутка содержимого моего приложения была немного медленнее. Поскольку мы устанавливаем высоту нашего контейнера прокрутки на 100% от себя, это препятствует прокрутке на основе щелчка/импульса на iOS. Если эта 100% высота короче (например, когда 100% высота 2000 пикселей становится 100% высотой 900 пикселей), прокрутка на основе импульса ухудшается. Прокрутка на основе движения/импульса происходит, когда вы проводите пальцами по поверхности сенсорного экрана, и страница прокручивается сама по себе. В моем случае я хотел, чтобы прокрутка на основе импульса происходила, чтобы пользователи могли быстро прокручивать, поэтому я избегал решений, которые устанавливают высоту 100%.

Другие попытки

Одно из решений, предложенных в Интернете и которое я пытался использовать в своем коде, показано ниже в качестве примера.

 html { width: 100%; position: fixed; overflow: hidden; } body { width: 100%; margin: 0; font-family: sans-serif; position: fixed; overflow: hidden; } .body-container { width: 100vw; height: calc(100vh - 100px); overflow-y: auto; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: fixed; bottom: 0; height: 100px; width: 100%; }

Этот код работает в Chrome и Firefox на macOS так же, как и предыдущее решение. Преимущество этого метода в том, что прокрутка не ограничена высотой 100%, поэтому прокрутка на основе импульса работает правильно. Однако в Safari нижний колонтитул исчезает:

Отсутствует нижний колонтитул в macOS Safari
Отсутствует нижний колонтитул в macOS Safari. (Большой превью)

В iOS Safari нижний колонтитул становится короче, а внизу появляется дополнительный прозрачный (или белый) зазор. Также пропадает возможность прокрутки страницы после прокрутки в самый низ. Вы можете увидеть белый пробел под нижним колонтитулом здесь:

Укороченный нижний колонтитул в iOS Safari
Укороченный нижний колонтитул в iOS Safari.

Одна интересная строка кода, которую вы можете часто видеть: -webkit-overflow-scrolling: touch; . Идея этого заключается в том, что он позволяет прокручивать заданный элемент на основе импульса. Это свойство описывается как «нестандартное» и «нестандартное» в документации MDN. Он отображается как «Недопустимое значение свойства» при проверке в Firefox и Chrome и не отображается как свойство в Desktop Safari. В конце концов я не использовал это свойство CSS.

Чтобы показать еще один пример решения, с которым вы можете столкнуться, и другой результат, который я нашел, я также попробовал код ниже:

 html { position: fixed; height: 100%; overflow: hidden; } body { font-family: sans-serif; margin: 0; width: 100vw; height: 100vh; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 110px; } footer { position: fixed; }

На самом деле это хорошо работает в разных настольных браузерах, прокрутка на основе импульса по-прежнему работает, а нижний колонтитул фиксируется внизу и не перемещается в настольных веб-браузерах. Возможно, самая проблематичная часть этого решения (и то, что делает его уникальным) заключается в том, что в iOS Safari нижний колонтитул всегда трясется и слегка искажается, и вы можете видеть содержимое под ним при каждой прокрутке.

Решения с JavaScript

После опробования некоторых первоначальных решений, использующих только HTML и CSS, я попробовал некоторые решения JavaScript. Я хотел бы добавить, что это то, что я не рекомендую вам делать, и лучше бы этого не делать. По моему опыту, обычно есть более элегантные и лаконичные решения, использующие только HTML и CSS. Тем не менее, я уже потратил много времени на опробование других решений, я подумал, что не мешало бы быстро посмотреть, есть ли какие-то альтернативные решения, использующие JavaScript.

Сенсорные события

Один из подходов к решению проблемы подпрыгивания прокрутки заключается в предотвращении событий touchmove или touchstart в window или document . Идея заключается в том, что события касания всего окна предотвращаются, в то время как события касания содержимого, которое вы хотите прокручивать, разрешены. Пример такого кода показан ниже:

 // Prevents window from moving on touch on older browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, false) // Allows content to move on touch. document.querySelector('.body-container').addEventListener('touchmove', function (event) { event.stopPropagation() }, false)

Я пробовал много вариантов этого кода, чтобы заставить прокрутку работать правильно. Предотвращение touchmove в window не имело значения. Использование document не имело значения. Я также пытался использовать как touchstart , так и touchmove для управления прокруткой, но эти два метода также не имели никакого значения. Я узнал, что вы больше не можете вызывать event.preventDefault() таким образом из соображений производительности. Вы должны установить для passive опции значение false в прослушивателе событий:

 // Prevents window from moving on touch on newer browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, {passive: false})

Библиотеки

Вы можете столкнуться с библиотекой под названием «iNoBounce», которая была создана, чтобы «предотвратить подпрыгивание вашего веб-приложения iOS при прокрутке». Одна вещь, на которую следует обратить внимание при использовании этой библиотеки прямо сейчас для решения проблемы, описанной в этой статье, заключается в том, что вам нужно использовать -webkit-overflow-scrolling . Еще одна вещь, которую следует отметить, это то, что более лаконичное решение, к которому я пришел (которое описано ниже), делает то же самое, что и для iOS. Вы можете проверить это самостоятельно, просмотрев примеры в репозитории GitHub и сравнив их с решением, которое я получил.

Поведение при прокрутке

Попробовав все эти решения, я узнал о CSS-свойстве overscroll-behavior . Свойство CSS overscroll-behavior было реализовано в Chrome 63 в декабре 2017 г. и в Firefox 59 в марте 2018 г. Это свойство, как описано в документации MDN, «позволяет вам управлять поведением браузера при переполнении прокрутки — что происходит, когда граница область прокрутки достигнута». Это было решение, которое я в итоге использовал.

Все, что мне нужно было сделать, это установить overscroll-behavior значение none в body моего веб-сайта, и я мог оставить position нижнего колонтитула fixed . Несмотря на то, что прокрутка на основе импульса применялась ко всей странице, а не к содержимому без нижнего колонтитула, это решение было достаточно хорошим для меня и удовлетворяло всем моим требованиям на тот момент, и мой нижний колонтитул больше не подскакивал неожиданно в Chrome. Возможно, полезно отметить, что в Edge это свойство помечено как находящееся в разработке. overscroll-behavior можно рассматривать как улучшение, если браузеры еще не поддерживают его.

Заключение

Если вы не хотите, чтобы ваши фиксированные верхние или нижние колонтитулы прыгали на ваших веб-страницах, теперь вы можете использовать свойство CSS overscroll-behavior .

Несмотря на то, что это решение работает по-разному в разных браузерах (отскок содержимого страницы по-прежнему происходит в Safari и Edge, тогда как в Firefox и Chrome этого нет), оно будет сохранять фиксированный верхний или нижний колонтитул при прокрутке до самого верха. или внизу сайта. Это краткое решение, и во всех протестированных браузерах прокрутка на основе импульса по-прежнему работает, поэтому вы можете очень быстро прокручивать большое количество содержимого страницы. Если вы создаете фиксированный верхний или нижний колонтитул на своей веб-странице, вы можете начать использовать это решение.