과도하게 설계된 앵커 링크(Anchor Link)
(thirty-five.com)- 앵커 링크는 단순히 버튼 클릭 → 제목으로 스크롤이라는 구조지만, 실제 구현 시 문제가 발생함
- 하단에 위치한 제목은 뷰포트 상단으로 정확히 스크롤되지 않음, 이로 인해 UX 저하 발생
- 이를 해결하기 위해 다양한 접근을 시도하며, 점점 더 정교하고 복잡한 방식으로 발전시킴
단순 해결: 패딩 추가
- 하단 제목이 스크롤에 잡히도록 여백을 추가하는 방식
- 델타를 계산해 padding 추가하면 해결 가능
- 하지만 디자인 팀에서 불필요한 여백을 꺼릴 수 있음
실용적 해결: 트리거 라인 이동
- 트리거 라인을 뷰포트 하단 쪽으로 이동시켜 하단 제목이 닿도록 조정
- 문제는 제목이 뷰포트 맨 아래에 위치하게 되어 가독성이 떨어짐
개선안: 가상 트리거 포인트 생성
- 실제 제목 위치는 그대로 두고, 트리거 발생 위치만 위쪽으로 이동한 가상 위치를 생성
- 각 제목마다 다른 조정을 적용할 수 있는 유연성 확보
- 하지만 첫 번째 제목은 너무 위로 이동되어 새로운 문제가 발생함 → 개별 조정이 필요
더 나은 방식: 트리거 위치 비례 이동
- 모든 트리거를 동일하게 이동하지 않고, 첫 제목은 그대로, 마지막 제목은 최대 이동
- 중간 제목은 위치에 따라 비례 이동함
- 제목 순서 유지 및 스크롤 도달 가능성 보장이라는 조건을 충족
- 이 방식은 단순하고 실용적, 대부분의 경우 적절히 작동
고급 접근: 커스텀 매핑 함수로 최적화
- 트리거 위치를 임의로 25% 위치에 두었기 때문에, 가상 위치가 원래 위치에서 너무 벗어날 수 있음
- 이를 해결하기 위해 MSE(Mean Squared Error) 를 활용한 최적화 접근을 도입
손실 함수 구성
- Anchor Penalty: 가상 제목 위치가 원래 위치에서 벗어난 정도
- Section Penalty: 섹션 간 거리(스크롤 길이)의 변화 정도
- 두 값을 가중치로 조절해 최적의 트리거 위치를 도출
제약 조건
- 페이지 범위 내 유지
- 첫 번째 제목은 위로 이동하지 않음
- 제목 순서 보존
인사이트: 단순 비례 이동의 한계
- 매우 긴 페이지(ex. 성경 전체)에서는 전체에 걸쳐 작은 이동을 누적 적용해야 하는 비효율 발생
- 페이지 길이가 길수록 오류가 커지고, UX에 악영향 가능성 있음
최종 해결: 스무스스텝 기반 가변 매핑 함수
- 각 제목의 위치를 0~1 사이의 값으로 정규화하고, 이를 기반으로 조정 비율 계산
- Smoothstep 함수(S(x) = 3x² - 2x³) 를 이용해 부드러운 전이 구현
- 조정 시작 위치
a
를 설정하여 특정 위치까지는 이동하지 않고 이후부터 부드럽게 상승- 예:
a = 0.4
이면 상위 40% 제목은 이동 없음, 하위 60%는 점진적 조정
- 예:
- 결과적으로, 상단 제목은 원래 위치 유지, 하단 제목은 최대 조정 적용 → 자연스러운 UX 제공
검증 및 마무리
- 최종 구현은 설계적 정교함과 실용성의 균형을 갖춘 솔루션
- 물론, 디자이너 피드백은 “...그냥 잘 작동하면 좋겠음”일 수 있음
- 하지만 적어도 이 블로그 글은 영원히 기억될 정교한 엔지니어링의 기록으로 남게 됨
Hacker News 의견
-
백엔드 개발자로서 프론트엔드 작업을 볼 때 가끔 복잡함에 놀라움을 느낌
- 훌륭한 기사이며 작업도 잘 되어 있지만, 단순한 스크롤에 이렇게 많은 복잡성을 도입해야 하는지 의문이 듦
-
사이드 내비게이션의 "활성 앵커" 표시의 UX 목적에 대한 질문
- 독자가 긴 섹션의 중간에 있을 때, 화면에 보이지 않는 헤딩을 대신하여 현재 섹션을 상기시켜 줄 수 있음
- 이는 스크롤한 헤딩이 아니라 화면에 보이는 섹션에 따라 작동함을 의미함
- 작은 섹션이 화면의 대부분을 차지하지 못할 경우, 활성 표시가 유용하지 않을 수 있음
-
앵커 링크의 가장 중요한 UX 기능은 다른 사람에게 보낼 수 있고 북마크로 저장할 수 있어야 함
- 특정 섹션을 북마크할 수 있는 기능이 페이지 상단부터 시작해 스크롤하거나 앵커 링크를 클릭하는 것보다 훨씬 편리함
- 이 웹사이트는 #anchor-name URL을 사용하지 않아 이 기능을 제공하지 않음
-
Jira의 앵커/영구 링크에 짜증이 나서 클릭했으나, 비슷하지만 다른 방식임
- 키보드로 앵커로 이동할 수 없음
- 저자에게 질문: 왜 HTML <a> 요소 대신 비상호작용 요소에 JS 이벤트 리스너를 사용했는지
-
메인 페이지 콘텐츠 아래에 패딩을 추가하는 것이 이상적임
- 콘텐츠의 끝부분이 뷰포트 하단에 고정되는 문제를 해결함
- 모바일에서는 90vh, 더 큰 화면에서는 50vh의 마진이 적절함
- 데스크탑에서는 90vh 마진이 어색해 보일 수 있음
-
현대 브라우저에서는 텍스트 조각을 사용하여 페이지의 특정 부분을 강조할 수 있음
- Chrome에서는 텍스트를 강조하고 오른쪽 클릭하여 "링크 복사"를 선택하면 됨
- 앵커 대신 특정 텍스트 부분을 강조하는 데 매일 사용함
-
여러 "활성" 상태를 허용하는 것도 가능함
- 콘텐츠가 길면 두 섹션의 헤더가 모두 "활성" 상태가 될 수 있음
- 짧은 콘텐츠에서는 너무 많은 부분이 강조될 수 있음
-
다른 댓글을 읽는 것이 재미있음
- 모바일에서 사이트 디자인이 흥미롭고 문제 해결이 명확히 전달됨
- 팝업 없이 기술적인 내용을 다루는 블로그를 읽는 것이 신선함
-
Firefox 데스크탑에서 "아름다운 솔루션"이 "중간 섹션"을 강조함
- 페이지 하단에 도달하지 않았을 때도 결론이 완전히 보임
- 화면에 보이는 모든 앵커를 강조하는 것이 답임
-
기사가 깔끔하고 블로그 디자인이 더 흥미로움
- 오른쪽 정렬 방식은 마음에 들지 않지만, 왼쪽 팝업의 인라인 활성화는 매우 멋짐