스토리 구성요소 빌드

웹에서 Instagram 스토리와 유사한 환경을 구축하는 방법에 관한 기본적인 개요입니다.

이 게시물에서는 반응형이고, 키보드 탐색을 지원하며, 여러 브라우저에서 작동하는 웹용 스토리 구성요소를 빌드하는 방법에 관한 생각을 공유하고자 합니다.

데모

이 스토리 구성요소를 직접 빌드하는 실습 데모를 보려면 스토리 구성요소 Codelab을 확인하세요.

동영상을 선호하는 경우 이 게시물의 YouTube 버전을 확인하세요.

개요

스토리 UX의 인기 있는 두 가지 예는 Snapchat 스토리와 Instagram 스토리입니다 (플릿은 제외). 일반적인 UX 용어로 스토리는 일반적으로 여러 구독을 탐색하기 위한 모바일 전용 탭 중심 패턴입니다. 예를 들어 Instagram에서 사용자는 친구의 스토리를 열고 스토리에 있는 사진을 살펴봅니다. 일반적으로 한 번에 많은 친구를 사귑니다. 기기의 오른쪽을 탭하면 사용자가 친구의 다음 스토리로 건너뜁니다. 오른쪽으로 스와이프하면 다른 친구로 건너뜁니다. 스토리 구성요소는 캐러셀과 매우 유사하지만 1차원 배열이 아닌 다차원 배열을 탐색할 수 있습니다. 각 캐러셀 내부에 캐러셀이 있는 것과 같습니다. 🤯

카드를 사용하여 다차원 배열을 시각화했습니다. 왼쪽에서 오른쪽으로 보라색 테두리 카드가 쌓여 있고 각 카드 안에는 1개 이상의 청록색 테두리 카드가 있습니다. 목록에 나열합니다.
친구의 첫 번째 캐러셀
두 번째 '스택형' 스토리 캐러셀
👍 목록의 목록, 즉 다차원 배열

작업에 적합한 도구 선택

전반적으로 몇 가지 중요한 웹 플랫폼 기능 덕분에 이 구성요소를 매우 간단하게 빌드할 수 있었습니다. 이러한 문제를 해결해 보겠습니다.

CSS 그리드

CSS 그리드에는 콘텐츠를 관리하는 강력한 방법이 몇 가지 있으므로 레이아웃이 CSS 그리드에 적합한 것으로 밝혀졌습니다.

친구 레이아웃

기본 .stories 구성요소 래퍼는 모바일 우선 가로 스크롤 뷰입니다.

.stories {
  inline-size: 100vw;
  block-size: 100vh;

  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;

  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}

/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
  max-inline-size: 480px;
  max-block-size: 848px;
}
Chrome DevTools의 기기 모드를 사용하여 그리드로 생성된 열을 강조 표시

grid 레이아웃을 분석해 보겠습니다.

  • 모바일에서는 100vh100vw로 표시 영역을 명시적으로 채우고 데스크톱에서는 크기를 제한합니다.
  • /는 행 및 열 템플릿을 구분합니다.
  • auto-flowgrid-auto-flow: column로 변환됩니다.
  • 자동 흐름 템플릿은 100%이며, 이 경우 스크롤 창 너비가 됩니다.

휴대전화에서는 행 크기가 표시 영역 높이이고 각 열이 표시 영역 너비라고 생각하면 됩니다. Snapchat 스토리 및 Instagram 스토리 예시를 계속 살펴보면 각 열은 친구의 스토리가 됩니다. 스크롤할 수 있도록 친구 스토리는 표시 영역 밖에서도 계속되도록 합니다. 그리드는 각 친구 스토리의 HTML을 배치하는 데 필요한 만큼의 열을 만들어 동적이고 반응형 스크롤 컨테이너를 만듭니다. 그리드를 사용하면 전체 효과를 중앙에 배치할 수 있습니다.

스태킹

각 친구에 대해 페이지로 나눌 수 있는 상태의 스토리가 필요합니다. 애니메이션과 기타 재미있는 패턴을 준비하기 위해 스택을 선택했습니다. 여기서 스택은 옆에서 보는 것이 아니라 샌드위치를 위에서 보는 것과 같습니다.

CSS 그리드를 사용하면 행과 열이 별칭 ([story])을 공유하는 단일 셀 그리드 (즉, 정사각형)를 정의할 수 있으며, 각 하위 요소는 별칭이 지정된 단일 셀 공간에 할당됩니다.

.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.story {
  grid-area: story;
  background-size: cover;
  
}

이렇게 하면 HTML이 스태킹 순서를 제어하고 모든 요소가 흐름에 유지됩니다. absolute 위치 지정이나 z-index와 관련해 아무것도 하지 않았으며 height: 100% 또는 width: 100%로 올바르게 박싱하지 않아도 됩니다. 상위 그리드에서 이미 스토리 사진 뷰포트의 크기를 정의했으므로 이러한 스토리 구성요소에 뷰포트를 채우라고 지시할 필요가 없습니다.

CSS 스크롤 스냅 포인트

CSS 스크롤 스냅 포인트 사양을 사용하면 스크롤 시 요소를 표시 영역에 쉽게 고정할 수 있습니다. 이러한 CSS 속성이 존재하기 전에는 JavaScript를 사용해야 했고, 최소한 까다로웠습니다. 사용 방법을 자세히 알아보려면 Sarah Drasner의 CSS 스크롤 스냅 포인트 소개를 확인하세요.

scroll-snap-points 스타일이 없는 경우와 있는 경우의 가로 스크롤 이 속성이 없으면 사용자는 평소와 같이 자유롭게 스크롤할 수 있습니다. 브라우저가 각 항목에 부드럽게 표시됩니다.
parent
.stories {
  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}
오버스크롤이 있는 상위 요소는 스냅 동작을 정의합니다.
어린이
.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
아동이 스냅 타겟이 되도록 선택합니다.

다음과 같은 이유로 스크롤 스냅 포인트를 선택했습니다.

  • 무료 접근성. 스크롤 스냅 포인트 사양에 따르면 왼쪽 화살표오른쪽 화살표 키를 누르면 기본적으로 스냅 포인트를 통해 이동해야 합니다.
  • 성장하는 사양. 스크롤 스냅 포인트 사양은 항상 새로운 기능과 개선사항을 제공하므로 내 Stories 구성요소는 앞으로 더 나아질 것입니다.
  • 구현 용이성 스크롤 스냅 포인트는 터치 중심의 가로 페이지로 나누기 사용 사례를 위해 설계되었습니다.
  • 무료 플랫폼 스타일 관성 모든 플랫폼은 기이한 스크롤 및 정지 스타일을 가질 수 있는 정규화된 관성과 달리 자체 스타일로 스크롤하고 정지합니다.

교차 브라우저 호환성

Opera, Firefox, Safari, Chrome, Android, iOS에서 테스트했습니다. 기능과 지원에 차이가 있는 웹 기능에 대한 간략한 설명은 다음과 같습니다.

하지만 일부 CSS가 적용되지 않아 일부 플랫폼에서 현재 UX 최적화가 누락되었습니다. 이러한 기능을 관리할 필요가 없다는 점이 마음에 들었고, 결국 다른 브라우저와 플랫폼에서도 이러한 기능을 사용할 수 있게 될 것이라고 생각합니다.

scroll-snap-stop

캐러셀은 CSS 스크롤 스냅 포인트 사양의 생성을 촉진한 주요 UX 사용 사례 중 하나였습니다. 스토리와 달리 캐러셀은 사용자가 상호작용한 후 각 이미지에서 항상 멈출 필요는 없습니다. 캐러셀을 빠르게 순환하는 것이 괜찮거나 권장될 수 있습니다. 반면 스토리는 하나씩 탐색하는 것이 가장 좋으며 scroll-snap-stop는 바로 이 기능을 제공합니다.

.user {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

이 게시물을 작성하는 시점에는 Chromium 기반 브라우저에서만 scroll-snap-stop가 지원됩니다. 브라우저 호환성에서 업데이트를 확인하세요. 하지만 차단기는 아닙니다. 지원되지 않는 브라우저에서는 사용자가 실수로 친구를 건너뛸 수 있습니다. 따라서 사용자는 더 주의해야 하며, 건너뛴 친구가 조회된 것으로 표시되지 않도록 JavaScript를 작성해야 합니다.

관심이 있다면 사양에서 자세히 알아보세요.

overscroll-behavior

모달을 스크롤하다가 갑자기 모달 뒤의 콘텐츠가 스크롤된 적이 있나요? overscroll-behavior을 사용하면 개발자가 스크롤을 포착하여 스크롤이 벗어나지 않도록 할 수 있습니다. 모든 종류의 행사에 적합합니다. 내 스토리 구성요소는 추가 스와이프 및 스크롤 동작이 구성요소를 벗어나지 않도록 하는 데 사용합니다.

.stories {
  overflow-x: auto;
  overscroll-behavior: contain;
}

Safari와 Opera는 이를 지원하지 않는 두 개의 브라우저였으며 이는 전혀 문제가 되지 않습니다. 이러한 사용자에게는 평소와 같은 오버스크롤 환경이 제공되며 이 개선사항을 인식하지 못할 수도 있습니다. 개인적으로는 스크롤 오버를 좋아하며 구현하는 거의 모든 스크롤 오버 기능에 포함하고 싶습니다. UX 개선으로만 이어질 수 있는 무해한 추가입니다.

scrollIntoView({behavior: 'smooth'})

사용자가 탭하거나 클릭하여 친구의 스토리 세트 끝에 도달하면 스크롤 스냅 포인트 세트의 다음 친구로 이동해야 합니다. JavaScript를 사용하면 다음 친구를 참조하고 뷰로 스크롤되도록 요청할 수 있습니다. 기본 사항에 대한 지원은 훌륭합니다. 모든 브라우저에서 스크롤하여 표시했습니다. 하지만 일부 브라우저는 'smooth'를 지원하지 않았습니다. 이는 스냅되는 대신 스크롤되어 표시된다는 의미입니다.

element.scrollIntoView({
  behavior: 'smooth'
})

여기에서 behavior: 'smooth'를 지원하지 않는 브라우저는 Safari뿐이었습니다. 브라우저 호환성에서 업데이트를 확인하세요.

실습

이제 제가 어떻게 했는지 아셨으니, 여러분은 어떻게 하시겠어요? 다양한 접근 방식을 통해 웹에서 빌드하는 모든 방법을 알아보세요. Glitch를 만들고, 내 버전으로 트윗하면 아래의 커뮤니티 리믹스 섹션에 추가해 드립니다.

커뮤니티 리믹스