'당겨서 표시'는 초기 로드 시 스크롤 가능한 영역 상단에 콘텐츠 (예: 검색창 또는 새로고침 컨트롤)가 숨겨져 있고 사용자가 아래로 당겨 (위로 스크롤) 표시할 수 있는 UI 패턴입니다. 이 패턴은 모바일 앱과 웹 앱에서 검색창, 필터, 기타 보조 컨트롤에 흔히 사용되며, 이러한 컨트롤은 액세스할 수 있어야 하지만 즉시 표시되지는 않습니다.
CSS 속성 scroll-initial-target는 이 패턴을 구현하는 선언적 CSS 전용 방법을 제공합니다. 기본 콘텐츠 요소에 scroll-initial-target: nearest를 설정하면 숨겨진 콘텐츠가 보이지 않도록 스크롤된 상태로 스크롤 컨테이너가 렌더링됩니다. 이전에는 개발자가 JavaScript (Element.scrollIntoView()) 또는 URL 프래그먼트 식별자 (#content-id)를 사용하여 이를 구현했는데, 두 방법 모두 제한사항이 있고 구현하기가 까다롭습니다.
구현 방법
당겨서 표시 패턴을 구현하려면 다음 단계를 따르세요.
- 스크롤 컨테이너 확인: 타겟 요소는 스크롤 컨테이너 (스크롤을 허용하는 오버플로가 있는 요소, 예:
overflow: auto) 내에 있어야 합니다. 루트<html>요소를 비롯한 모든 상위 요소가 될 수 있습니다. - 숨겨진 요소 정의: 숨기려는 콘텐츠 (예: 검색창)를 스크롤 컨테이너 내의 첫 번째 하위 요소로 배치합니다. 이 요소는 초기 로드 시 뷰에서 스크롤됩니다.
- 기본 콘텐츠 정의: 숨겨진 요소 바로 뒤에 기본 콘텐츠 요소를 배치합니다. 사용자가 가장 먼저 보게 되는 요소입니다.
- 기본 콘텐츠 타겟팅: 기본 콘텐츠 요소에
scroll-initial-target: nearest를 적용하여 스크롤 컨테이너가 스크롤되어 표시되도록 렌더링하여 그 위의 요소를 숨깁니다. - 스크롤 스냅 추가: 숨겨진 요소가 항상 완전히 표시되거나 완전히 숨겨지도록 하려면 (부분적으로 스크롤된 상태로 유지되지 않음) 스크롤 컨테이너에
scroll-snap-type: y mandatory를 추가하고 숨겨진 요소와 기본 콘텐츠 요소 모두에scroll-snap-align: start를 추가합니다.
예시 코드: 당겨서 검색 표시
/**
* ANCESTOR: Define the scroll container.
* Scroll snapping ensures the search bar is always
* either fully visible or fully hidden.
*/
.scroll-container {
height: 100vh;
overflow-y: auto;
scroll-snap-type: y mandatory;
}
/**
* HIDDEN ELEMENT: The search bar hidden above the fold on load.
* It has scroll-snap-align so it snaps into place when pulled down.
*/
.search-bar {
height: 60px;
scroll-snap-align: start;
}
/**
* MAIN CONTENT + TARGET: The element the user sees first.
* scroll-snap-align makes it a valid snap point.
* scroll-initial-target tells the browser to scroll here on
* initial render, hiding the search bar above it.
*/
.main-content {
scroll-snap-align: start;
scroll-initial-target: nearest;
}
전략적 구현 및 권장사항
- 권장사항: 로드 시 스크롤 가능한 영역의 특정 부분에 사용자의 주의를 끌고 맨 위에 있는 검색창과 같은 주변 UI 단위를 의도적으로 숨기려면
scroll-initial-target: nearest를 사용하세요. - 접근성 포커스와 혼동하지 마세요. 이 속성은 시각적 표시 영역만 이동하며 키보드 포커스는 이동하지 않습니다. 타겟이 키보드 사용자의 시작점이 되도록 하려면
element.focus()를 수동으로 관리해야 합니다. - 로드 시 부드러운 '스크롤' 애니메이션이 필요한 경우 이 속성을 사용하지 마세요. 이 속성은 불연속적이며 레이아웃 단계에서 위치를 즉시 설정합니다.
- 동일한 스크롤 가능한 컨테이너 내의 여러 요소에
scroll-initial-target를 설정하지 마세요. 여러 요소가scroll-initial-target: nearest를 지정하는 경우 브라우저는 DOM 트리 순서에서 먼저 표시되는 요소를 선택합니다. - 우선순위 계층 구조를 고려하세요. URL 프래그먼트 (예:
example.com/#top)와 컨테이너 수준scroll-start속성은 모두scroll-initial-target보다 우선 적용됩니다.
대체 전략
아직 API를 지원하지 않는 브라우저의 경우 JavaScript 대체 기능을 사용합니다. 콘텐츠를 당겨서 표시하려면 기본 콘텐츠가 컨테이너의 start (상단)에 바인딩되어야 합니다.
/**
* Progressive Enhancement Fallback
*/
document.addEventListener("DOMContentLoaded", () => {
// Check for native CSS support
if (!CSS.supports("scroll-initial-target", "nearest")) {
const targetContent = document.querySelector('.main-content.target');
if (targetContent) {
// Use behavior: "instant" to mimic the native CSS behavior
// 'block: start' should match your CSS 'scroll-snap-align' (or expected top position)
targetContent.scrollIntoView({ behavior: 'instant', block: 'start' });
}
}
});