귀하의 웹 사이트에서 스크롤 바운스

게시 됨: 2022-03-10
빠른 요약 ↬ 이 기사에서는 스크롤 바운스의 효과와 다양한 웹 브라우저에서 작동하는 방식에 대해 설명합니다. 여기에는 스크롤 바운스를 방지하는 데 사용할 수 있는 웹에서 제안된 여러 솔루션에 대한 리뷰가 포함되어 있습니다. 2017년 12월 Chrome과 2018년 3월 Firefox에서 구현된 CSS 속성 overscroll-behavior 도 이 문서에서 설명합니다. 이 효과를 잘 이해하면 고정 요소가 있는 웹 사이트를 구축하거나 디자인하는 데 매우 유용합니다.

스크롤 바운싱(스크롤 '고무 밴딩' 또는 '탄력적 스크롤'이라고도 함)은 페이지나 HTML 요소의 맨 위로 또는 맨 아래로 스크롤할 때 표시되는 효과를 나타내는 데 자주 사용됩니다. 터치스크린이나 트랙패드를 사용하는 장치에서 페이지 또는 요소와 빈 공간은 요소 또는 페이지가 다시 튀어나와 상단/하단에 다시 정렬되기 전에 잠시 볼 수 있습니다(터치/손가락을 놓을 때). CSS 요소 간의 스크롤 스냅에서도 유사한 효과가 발생하는 것을 볼 수 있습니다.

그러나 이 문서에서는 웹 페이지의 맨 위 또는 맨 아래로 스크롤할 때 스크롤 바운싱에 중점을 둡니다. 즉, 스크롤 포트가 스크롤 경계에 도달했을 때입니다.

데이터 수집, 강력한 방법

CSS를 사용하여 통계를 수집할 수 있다는 사실을 알고 계셨습니까? 실제로 Google Analytics를 사용하여 UI 상호 작용을 추적하기 위한 CSS 전용 접근 방식도 있습니다. 관련 기사 읽기 →

스크롤 바운싱을 잘 이해하면 웹사이트 구축 방법과 페이지 스크롤 방법을 결정하는 데 도움이 되기 때문에 매우 유용합니다.

페이지 이동 시 fixed 요소를 보고 싶지 않은 경우 스크롤 바운스가 바람직하지 않습니다. 몇 가지 예는 다음과 같습니다. 머리글이나 바닥글을 특정 위치에 고정하려는 경우, 메뉴와 같은 다른 요소를 고정하려는 경우, 또는 페이지가 스크롤 및 페이지 맨 위나 맨 아래에 추가 스크롤이 발생하여 웹사이트 방문자를 혼란스럽게 하는 것을 원하지 않습니다. 이 기사에서는 웹 페이지의 맨 위 또는 맨 아래에서 스크롤 바운싱을 처리할 때 직면하는 문제에 대한 몇 가지 솔루션을 제안합니다.

점프 후 더! 아래에서 계속 읽기 ↓

효과와 나의 첫 만남

나는 오래전에 구축한 웹사이트를 업데이트할 때 이 효과를 처음 발견했습니다. 여기에서 웹사이트를 볼 수 있습니다. 페이지 하단의 바닥글은 페이지 하단의 위치에 고정되어 전혀 움직이지 않아야 했습니다. 동시에 페이지의 주요 내용을 위아래로 스크롤할 수 있어야 했습니다. 이상적으로는 다음과 같이 작동합니다.

macOS의 Firefox에서 스크롤 바운스
macOS의 Firefox에서 스크롤이 튕깁니다. (큰 미리보기)

현재 Firefox 또는 터치스크린이나 트랙패드가 없는 장치의 모든 브라우저에서 이 방식으로 작동합니다. 하지만 당시 저는 MacBook에서 Chrome을 사용하고 있었습니다. 내 웹사이트가 제대로 작동하지 않는다는 것을 발견했을 때 트랙패드를 사용하여 페이지 하단으로 스크롤했습니다. 여기서 무슨 일이 일어 났는지 볼 수 있습니다.

macOS의 Chrome에서 스크롤 바운싱
macOS의 Chrome에서 스크롤이 튕깁니다. (큰 미리보기)

안 돼! 이것은 일어나야 할 일이 아니었습니다! CSS position 속성을 fixed 값으로 설정하여 바닥글의 위치를 ​​페이지 하단으로 설정했습니다. 이것은 또한 어떤 position: fixed; 이다. CSS 2.1 사양에 따르면 "box"(이 경우 진한 파란색 바닥글)가 고정되면 "뷰포트를 기준으로 고정되어 스크롤 시 움직이지 않습니다." 이것이 의미하는 바는 페이지를 위아래로 스크롤할 때 바닥글이 움직이지 않아야 한다는 것입니다. Chrome에서 무슨 일이 일어나고 있는지 보았을 때 이것이 걱정되었습니다.

이 기사를 더 완벽하게 만들기 위해 아래에서 Mobile Edge, Mobile Safari 및 Desktop Safari 모두에서 페이지가 스크롤되는 방법을 보여 드리겠습니다. 이것은 Firefox 및 Chrome에서 스크롤할 때 발생하는 것과 다릅니다. 이것이 정확히 동일한 코드가 현재 다른 방식으로 어떻게 작동하는지 더 잘 이해하는 데 도움이 되기를 바랍니다. 현재 서로 다른 웹 브라우저에서 동일한 방식으로 작동하는 스크롤링을 개발하는 것이 과제입니다.

macOS의 Safari에서 스크롤이 튕깁니다. iOS의 Edge 및 Safari에서도 유사한 효과를 볼 수 있습니다.
macOS의 Safari에서 스크롤이 튕깁니다. iOS의 Edge 및 Safari에서도 유사한 효과를 볼 수 있습니다. (큰 미리보기)

솔루션 검색

내 첫 번째 생각 중 하나는 모든 브라우저에서 이 문제를 쉽고 빠르게 해결할 수 있는 방법이 있다는 것이었습니다. 이것이 의미하는 바는 몇 줄의 CSS 코드가 필요하고 JavaScript가 관련되지 않는 솔루션을 찾을 수 있다고 생각했다는 것입니다. 따라서 내가 한 첫 번째 일 중 하나는 이것을 달성하기 위해 노력하는 것이었습니다. 테스트에 사용한 브라우저는 macOS 및 Windows 10의 Chrome, Firefox 및 Safari, iOS의 Edge 및 Safari입니다. 이 브라우저의 버전은 이 기사를 작성하는 시점(2018년)의 최신 버전이었습니다.

HTML 및 CSS 전용 솔루션

절대 및 상대 위치

처음 시도한 것 중 하나는 바닥글을 만드는 데 익숙했기 때문에 절대 및 상대 위치 지정을 사용하여 바닥글을 배치하는 것이었습니다. 아이디어는 내 웹 페이지를 100% 높이로 설정하여 바닥글이 항상 고정 높이로 페이지 맨 아래에 있도록 하는 것입니다. 반면 내용은 바닥글 높이에서 100%를 뺀 값을 차지하고 스크롤할 수 있습니다. 또는 calc 를 사용하는 대신 padding-bottom 을 설정하고 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; ). 이에 비해 이 솔루션의 한 가지 장점은 스크롤이 전체 페이지가 아니라 바닥글이 없는 페이지의 내용에만 적용된다는 것입니다. 이 방법의 가장 큰 문제점은 모바일 사파리에서 애플리케이션의 바닥글과 콘텐츠가 동시에 움직인다는 점이다. 이로 인해 빠르게 스크롤할 때 이 접근 방식이 매우 문제가 됩니다.

절대 및 상대 위치
절대 및 상대 위치.

내가 원하지 않는 또 다른 효과는 처음에는 알아차리기 어려웠고 더 많은 솔루션을 시도한 후에야 발생한다는 것을 깨달았습니다. 이것은 내 응용 프로그램의 내용을 스크롤하는 것이 약간 느리다는 것입니다. 스크롤 컨테이너의 높이를 자체의 100%로 설정하기 때문에 iOS에서 플릭/모멘텀 기반 스크롤을 방해합니다. 100% 높이가 더 짧으면(예: 2000px의 100% 높이가 900px의 100% 높이가 되는 경우) 운동량 기반 스크롤이 악화됩니다. 플릭/모멘텀 기반 스크롤은 손가락으로 터치스크린 표면을 플릭하고 페이지가 저절로 스크롤될 때 발생합니다. 제 경우에는 사용자가 빠르게 스크롤할 수 있도록 모멘텀 기반 스크롤이 발생하기를 원했기 때문에 높이를 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%; }

이 코드는 이전 솔루션과 동일한 방식으로 macOS의 Chrome 및 Firefox에서 작동합니다. 이 방법의 장점은 스크롤이 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를 사용하는 몇 가지 대체 솔루션이 있는지 빨리 확인하는 것이 나쁘지 않을 것이라고 생각했습니다.

터치 이벤트

스크롤 바운스 문제를 해결하는 한 가지 방법은 window 이나 document 에서 touchmove 또는 touchstart 이벤트를 방지하는 것입니다. 이에 대한 아이디어는 전체 창의 터치 이벤트가 방지되는 반면 스크롤하려는 콘텐츠의 터치 이벤트는 허용된다는 것입니다. 다음은 이와 같은 코드의 예입니다.

 // 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)

스크롤이 제대로 작동하도록 하기 위해 이 코드의 여러 변형을 시도했습니다. window 에서 touchmove 를 방지해도 아무런 차이가 없었습니다. document 를 사용해도 차이가 없었습니다. 또한 touchstarttouchmove 를 모두 사용하여 스크롤을 제어하려고 시도했지만 이 두 가지 방법도 차이가 없었습니다. 성능상의 이유로 더 이상 이 방법으로 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 에 대해 알게 되었습니다. overscroll-behavior CSS 속성은 2017년 12월 Chrome 63에서, 2018년 3월 Firefox 59에서 구현되었습니다. MDN 문서에 설명된 대로 이 속성을 사용하면 "브라우저의 스크롤 오버플로 동작을 제어할 수 있습니다. 스크롤 영역에 도달했습니다." 이것이 내가 결국 사용한 솔루션이었습니다.

내가해야 할 일은 내 웹 사이트 body 에서 overscroll-behaviornone 으로 설정하고 바닥 글의 positionfixed 로 둘 수 있었습니다. 모멘텀 기반 스크롤이 바닥글이 없는 콘텐츠가 아닌 전체 페이지에 적용되었지만 이 솔루션은 나에게 충분했고 그 시점의 모든 요구 사항을 충족했으며 바닥글이 Chrome에서 더 이상 예기치 않게 바운스되지 않았습니다. Edge에는 현재 개발 중인 것으로 플래그가 지정된 이 속성이 있다는 점에 유의하는 것이 유용할 수 있습니다. 브라우저가 아직 지원하지 않는 경우 overscroll-behavior 를 개선된 것으로 볼 수 있습니다.

결론

고정 머리글이나 바닥글이 웹 페이지에서 바운스되는 것을 원하지 않으면 이제 overscroll-behavior CSS 속성을 사용할 수 있습니다.

이 솔루션이 다른 브라우저에서 다르게 작동한다는 사실에도 불구하고(페이지 콘텐츠의 바운싱은 Safari 및 Edge에서 여전히 발생하지만 Firefox 및 Chrome에서는 발생하지 않음) 맨 위로 스크롤할 때 머리글 또는 바닥글을 고정된 상태로 유지합니다. 또는 웹사이트 하단. 간결한 솔루션이며 테스트된 모든 브라우저에서 운동량 기반 스크롤이 여전히 작동하므로 많은 페이지 콘텐츠를 매우 빠르게 스크롤할 수 있습니다. 웹 페이지에 고정 머리글 또는 바닥글을 구축하는 경우 이 솔루션을 사용할 수 있습니다.