Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] 다양한 높이를 가진 페이지 간의 스크롤 동기화 문제 해결 #132

Closed
jaem1n207 opened this issue May 13, 2024 · 0 comments
Assignees
Labels
bug Something isn't working

Comments

@jaem1n207
Copy link
Owner

jaem1n207 commented May 13, 2024

문제 인식

다양한 높이를 가진 웹 페이지 간의 스크롤 위치를 백분율로 동기화하는 기능에 문제가 있다는 것을 사용자의 리뷰에서 발견했습니다:

works great – if i could request one feature it would be the ability to sync by scroll percentage vs. scroll y-position. this helps a lot when comparing on screens of different pixel densities. (e.g., if we are comparing a page on two screens that renders with heights 500px and 1000px, scrolling to the bottom of the 500px tall tab would scroll to the bottom of the 1000px tab as well.)

사용자는 한 페이지에서 스크롤을 최하단으로 내렸을 때, 다른 페이지에서도 동일하게 최하단으로 스크롤되기를 기대했으나, 실제로는 그렇지 않았다는 내용이었습니다.

애초에 화면 크기나 해상도 차이에 관계없이 두 화면에서 동일한 비율로 스크롤이 동기화될 수 있도록 스크롤 위치를 절대적인 픽셀 값이 아닌, 문서의 전체 높이에 대한 백분율(%)로 동기화하도록 기능을 작성했었습니다.

그래서 처음엔 스크롤 위치를 절대적인 px 값으로도 동기화할 수 있도록 옵션을 추가해달라는 요청으로 이해했습니다. 하지만 사용자가 제시한 예시대로 재현해보기로 했고 여기서 문제를 발견할 수 있었습니다.

문제 분석

사용자가 제시한 문제를 재현하기 위해 두 개의 다른 높이를 가진 웹 페이지를 생성하고, 스크롤 동기화를 테스트할 수 있는 간단한 HTML과 JS 코드를 작성했습니다: https://codepen.io/jaem1n207/pen/bGyNPBE (Codepen 결과 화면의 Before 섹션 참고)

문제의 원인을 분석하기 위해 기존의 스크롤 동기화 로직을 천천히 살펴보았는데요. 기존 로직은 scrollTop 값을 scrollHeight로 나누어 스크롤 위치의 백분율을 계산하고 있었습니다. 그러나 이런 게산 방식은 clientHeight를 고려하지 않아 실제 스크롤 가능한 범위를 정확히 반영하지 못했습니다:

const scrollPosition = window.scrollY || document.documentElement.scrollTop || document.body.scrollTop || 0;
const scrollHeight = document.documentElement.scrollHeight;
const scrollYPercentage = scrollPosition / scrollHeight;

const nextScrollPosition = scrollYPercentage * scrollHeight;
window.scrollTo({ top: nextScrollPosition });
  • scrollPosition: 스크롤바의 현재 위치를 나타냅니다.
  • scrollHeight: 스크롤 가능한 전체 문서의 높이를 나타냅니다.

여기서 scrollPosition의 최대값은 scrollHeight에서 뷰포트(보이는 영역)의 높이를 뺀 값입니다. 이로 인해 백분율 계산이 잘못되어 스크롤 동기화가 정확히 이루어지지 않는 문제가 발생하던 것이었습니다.

예를 들어, scrollHeight가 3500인 문서가 있고 뷰포트의 높이가 1400이라고 가정하면 scrollY의 최대값은 2100입니다.

해결 방안

문제를 해결하기 위해, 스크롤 백분율을 계산할 때 clientHeight를 고려하여 실제 스크롤 가능한 높이를 사용하도록 로직을 수정했습니다:

const scrollPosition = window.scrollY || document.documentElement.scrollTop || document.body.scrollTop || 0;
const scrollHeight = document.documentElement.scrollHeight;
+ const clientHeight = document.documentElement.clientHeight;

- const scrollYPercentage = scrollPosition / scrollHeight;
// 스크롤 가능한 최대 높이에서 뷰포트 높이를 빼고, 현재 스크롤 위치를 나누어 백분율을 계산
+ const scrollYPercentage = scrollHeight === clientHeight ? 0 : scrollPosition / (scrollHeight - clientHeight);

- const nextScrollPosition = scrollYPercentage * scrollHeight;
// 다른 문서의 스크롤 위치를 계산할 때도 동일하게 뷰포트 높이를 고려
+ const nextScrollPosition = scrollYPercentage * (scrollHeight - clientHeight);
// 다른 문서의 스크롤 위치 조정
window.scrollTo({ top: nextScrollPosition });

이제 스크롤 가능한 범위를 기준으로 백분율을 계산하게 됩니다.

결과

scroll-sync-problem

이전 스크롤 로직과 변경 후 스크롤 로직은 코드펜에서 확인할 수 있습니다.

@jaem1n207 jaem1n207 added the bug Something isn't working label May 13, 2024
@jaem1n207 jaem1n207 self-assigned this May 13, 2024
github-actions bot pushed a commit that referenced this issue May 13, 2024
## [2.3.1](v2.3.0...v2.3.1) (2024-05-13)

### Bug Fixes

* 스크롤 백분율 계산할 때 문서 실제 보이는 뷰포트 높이 고려하도록 수정 ([c24ff10](c24ff10)), closes [#132](#132)
@jaem1n207 jaem1n207 pinned this issue May 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant