CSS 스크롤 스냅으로 잘 제어되는 스크롤

스크롤 스냅 위치를 선언하여 잘 제어되는 스크롤 환경을 만듭니다.

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

CSS 스크롤 스냅 기능을 사용하면 웹 개발자가 스크롤 스냅 위치를 선언하여 잘 제어되는 스크롤 환경을 만들 수 있습니다. 페이지가 매겨진 기사와 이미지 캐러셀이 흔히 사용되는 두 가지 예입니다. CSS 스크롤 스냅은 이러한 인기 있는 UX 패턴을 빌드하는 데 사용하기 쉽고 일관된 API를 제공합니다.

배경

스크롤 스냅 케이스

스크롤은 웹에서 콘텐츠와 상호작용할 수 있는 자연스럽고 인기 있는 방법입니다. 이는 화면에서 동시에 볼 수 있는 것보다 더 많은 정보에 액세스할 수 있는 플랫폼의 기본적인 수단이며, 화면 공간이 제한된 모바일 플랫폼에서 특히 중요해집니다. 따라서 웹 작성자는 심층적인 계층 구조보다는 스크롤 가능한 플랫 목록으로 콘텐츠를 구성하는 것을 점점 더 선호합니다.

스크롤의 주요 단점은 정밀도가 낮다는 것입니다. 스크롤이 단락이나 문장에 맞춰지는 경우는 거의 없습니다. 이는 페이지 또는 이미지 중간에서 스크롤이 끝나서 부분적으로 표시되는 경우 의미 있는 경계가 있는 페이지로 나뉘거나 항목별 콘텐츠에서 더 두드러집니다. 이러한 사용 사례에는 잘 제어된 스크롤 환경이 도움이 됩니다.

웹 개발자는 이러한 단점을 해결하기 위해 오랫동안 자바스크립트 기반 솔루션을 사용하여 스크롤을 제어해 왔습니다. 그러나 JavaScript 기반 솔루션은 스크롤 맞춤설정 프리미티브가 부족하거나 합성 스크롤에 액세스할 수 없으므로 최고 품질 솔루션을 제공하지 못합니다. CSS Scroll Snap은 여러 브라우저에서 일관되게 작동하는 빠르고 사용하기 쉬운 높은 충실도의 솔루션을 보장합니다.

CSS 스크롤 스냅을 사용하면 웹 작성자가 완료할 스크롤 작업의 경계로 각 스크롤 컨테이너를 표시할 수 있습니다. 그런 다음 브라우저는 스크롤 작업의 사양, 스크롤 컨테이너의 레이아웃 및 공개 상태, 맞추기 위치의 세부정보에 따라 가장 적절한 종료 위치를 선택하고 부드럽게 애니메이션을 적용합니다. 이전 예시로 돌아가서, 사용자가 캐러셀을 스크롤하면 표시된 이미지가 제자리에 맞춰집니다. JavaScript에서 스크롤 조정이 필요하지 않습니다.

이미지 캐러셀과 함께 CSS 스크롤 스냅을 사용하는 예
이미지 캐러셀과 함께 CSS 스크롤 스냅을 사용하는 예 여기서 스크롤 맞추기를 사용하면 스크롤이 끝날 때 이미지가 가로 가운데가 스크롤 컨테이너의 가로 가운데에 정렬됩니다.

CSS 스크롤 스냅

스크롤 스냅은 스크롤 작업이 완료된 후 스크롤 컨테이너의 스크롤 오프셋을 원하는 스냅 위치가 되도록 조정하는 작업입니다.

스크롤 컨테이너는 scroll-snap-type 속성을 사용하여 스크롤 맞추기를 선택할 수 있습니다. 이렇게 하면 브라우저에 이 스크롤 컨테이너를 하위 요소가 생성한 맞추기 위치로 맞추기를 고려해야 한다는 것을 알 수 있습니다. scroll-snap-type는 스크롤이 발생하는 축(x, y, both)과 맞추기 엄격도(mandatory, proximity)를 결정합니다. 이에 대해서는 나중에 자세히 설명합니다.

맞추기 위치는 요소에 원하는 정렬을 선언하여 생성할 수 있습니다. 이 위치는 가장 가까운 상위 스크롤 컨테이너와 요소가 지정된 축에 지정된 대로 정렬되는 스크롤 오프셋입니다. 각 축에는 start, end, center 정렬이 가능합니다.

start 정렬은 스크롤 컨테이너 스냅포트 시작 가장자리가 요소 맞추기 영역 시작 가장자리와 플러시되어야 함을 의미합니다. 마찬가지로 endcenter 정렬은 스크롤 컨테이너 스냅포트의 끝 가장자리 또는 중앙이 요소 맞추기 영역 끝 가장자리 또는 중앙으로 플러시되어야 함을 의미합니다.

가로 스크롤 축의 다양한 정렬 예

다음 예는 이러한 개념을 사용하는 방법을 보여줍니다.

스크롤 맞추기의 일반적인 사용 사례는 이미지 캐러셀입니다. 예를 들어 스크롤할 때 각 이미지에 맞춰지는 가로 이미지 캐러셀을 만들려면 가로축에 필수 scroll-snap-type가 포함되도록 스크롤 컨테이너를 지정할 수 있습니다. 맞추기로 이미지가 캐러셀 내에서 중앙에 배치되도록 각 이미지를 scroll-snap-align: center로 설정합니다.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

맞추기 위치는 요소와 연결되므로 맞추기 알고리즘은 요소와 스크롤 컨테이너 크기를 고려하여 언제 어떻게 맞춰야 할지 결정할 수 있습니다. 예를 들어 이미지 하나가 캐러셀보다 큰 경우를 생각해 보겠습니다. 단순한 맞추기 알고리즘을 사용하면 사용자가 전체 이미지를 보기 위해 화면을 이동하는 것을 방지할 수 있습니다. 하지만 사양에 따라 이러한 경우를 감지하고 사용자가 이미지 내에서 가장자리에서만 자유롭게 스크롤할 수 있도록 구현해야 합니다.

데모 보기 | 소스

예: 방문한 제품 페이지

스크롤 맞추기가 유용할 수 있는 또 다른 일반적인 경우는 세로로 스크롤할 수 있는 논리 섹션이 여러 개 있는 페이지(예: 일반적인 제품 페이지)입니다. scroll-snap-type: y proximity;는 이와 같은 사례에 더 적합합니다. 이 기능은 사용자가 특정 섹션의 중간으로 스크롤할 때 간섭을 일으키지 않으며, 사용자가 충분히 가까이 스크롤하면 맞춰서 새 섹션으로 주의를 돌리기도 합니다.

이를 달성하는 방법은 다음과 같습니다.

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

스크롤 패딩 및 여백

제품 페이지의 상단 헤더가 고정되어 있습니다. 또한 위 콘텐츠에 관한 디자인 신호를 사용자에게 제공하기 위해 스크롤 컨테이너를 맞출 때 상단 섹션의 일부가 계속 표시되도록 요구했습니다.

scroll-padding 속성은 스크롤 컨테이너의 유효한 표시 가능 영역 또는 스크롤 스냅 정렬을 계산할 때 사용되는 스냅포트의 유효한 표시 영역을 조정하는 데 사용할 수 있는 새로운 css 속성입니다. 속성은 스크롤 컨테이너의 패딩 상자에 인셋을 정의합니다. 이 예에서는 15vh 추가 인셋이 상단에 추가되었습니다. 이는 브라우저가 스크롤 컨테이너의 상단 가장자리 아래 15vh를 스크롤 스냅을 위한 세로 시작 가장자리로 고려하도록 지시합니다. 맞추기에서는 맞추기 대상 요소의 시작 가장자리가 새 위치와 플러싱되므로 위쪽에 공간이 남게 됩니다.

scroll-margin 속성은 맞추기 스크롤 컨테이너에서 scroll-padding가 작동하는 방식과 유사하게 맞추기 대상 유효 상자를 조정하는 데 사용되는 출력 크기를 정의합니다.

이 두 속성에는 'snap'라는 단어가 없습니다. 이는 실제로 모든 관련 스크롤 작업에 맞게 상자를 수정하며 스크롤 스냅만이 아닙니다. 이는 의도적인 것입니다. 예를 들어 Chrome에서는 PageDown 및 PageUp과 같은 페이징 스크롤 작업을 위한 페이지 크기를 계산할 때와 Element.scrollIntoView() 작업의 스크롤 크기를 계산할 때 이러한 요소를 고려합니다.

데모 보기 | 소스

다른 스크롤 API와의 상호작용

DOM Scrolling API

스크롤 맞추기는 스크립트에 의해 시작된 스크롤 작업을 비롯한 모든 스크롤 작업 후에 발생합니다. Element.scrollTo와 같은 API를 사용하면 브라우저는 작업의 의도된 스크롤 위치를 계산한 다음 적절한 맞추기 로직을 적용하여 최종 맞추기 위치를 찾습니다. 따라서 사용자 스크립트에서 맞추기를 수동으로 계산할 필요가 없습니다.

부드러운 스크롤

부드러운 스크롤은 프로그래매틱 스크롤 작업의 동작을 제어하며 스크롤 스냅은 대상을 결정합니다. 두 형식은 스크롤의 직각을 제어하므로 함께 사용하고 서로를 보완할 수 있습니다.

오버스크롤 동작

Overscroll 동작 API는 여러 요소에 걸쳐 스크롤이 연결되는 방식을 제어하며 스크롤 스냅의 영향을 받지 않습니다.

주의사항 및 권장사항

대상 요소 간의 간격이 넓을 때 필수 맞추기를 사용하지 마세요. 이로 인해 맞추기 위치 사이에 있는 콘텐츠에 액세스할 수 없게 됩니다.

많은 경우 스크롤 스냅을 특성 감지 없이 개선사항으로 추가할 수 있습니다. 필요한 경우 @supports 또는 CSS.supports를 사용하여 CSS 스크롤 스냅 지원을 감지합니다. 지원 중단된 사양에도 있는 scroll-snap-type를 사용하지 마세요.

CSS의 기능 감지

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

JavaScript에서 기능 감지

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

Element.scrollTo와 같은 프로그래매틱 방식의 스크롤 API가 항상 요청된 스크롤 오프셋에서 완료된다고 가정하지 마세요. 스크롤 맞추기에서는 프로그래매틱 스크롤이 완료된 후 스크롤 오프셋을 조정할 수 있습니다. 다른 이유로 스크롤이 중단되었을 수 있으므로 이는 스크롤 스냅하기 전에도 좋은 가정은 아니지만 스크롤 스냅의 경우에는 특히 그렇습니다.

향후 작업

Chrome팀의 최근 설문조사에서는 스크롤 환경에 초점을 맞췄습니다. 설문조사 결과, 플러그인 라이브러리와 CSS 간의 격차를 좁히기 위해 추가 작업이 필요한 몇 가지 영역이 확인되었습니다. 예정된 작업은 다음을 포함하여 scroll-snap에 중점을 둡니다.

  1. 브라우저 간 API 가용성 및 호환성
  2. scroll-start와 같은 새로운 CSS API 작업
  3. snapChanged()와 같은 새로운 JS 이벤트 작업