Tabs 구성요소 빌드

iOS 및 Android 앱에 있는 것과 유사한 탭 구성요소를 빌드하는 방법에 관한 기본적인 개요입니다.

이 게시물에서는 반응형이고, 여러 기기 입력을 지원하며, 여러 브라우저에서 작동하는 웹용 Tabs 구성요소를 빌드하는 생각을 공유하고자 합니다. 데모 사용해 보기

데모

동영상을 선호한다면 이 게시물의 YouTube 버전을 참조하세요.

개요

탭은 디자인 시스템의 일반적인 구성요소이지만 다양한 모양과 형태를 취할 수 있습니다. 먼저 <frame> 요소를 기반으로 빌드된 데스크톱 탭이 있었지만 이제는 물리 속성을 기반으로 콘텐츠에 애니메이션을 적용하는 버터형 모바일 구성요소가 있습니다. 공간 절약이라는 동일한 일을 하려고 합니다.

오늘날 탭 사용자 환경의 핵심은 디스플레이 프레임의 콘텐츠 공개 상태를 전환하는 버튼 탐색 영역입니다. 다양한 콘텐츠 영역이 동일한 공간을 공유하지만 탐색에서 선택한 버튼을 기반으로 조건부로 표시됩니다.

웹이 구성요소 개념에 적용한 스타일이 매우 다양하여 콜라주가 매우 혼란스러울 수 있습니다.
지난 10년간의 탭 구성요소 웹 디자인 스타일로 구성된 콜라주

웹 전략

이 구성요소는 대체로 다음과 같은 몇 가지 중요한 웹 플랫폼 기능 덕분에 빌드할 수 있습니다.

  • scroll-snap-points: 적절한 스크롤 중지 위치와 함께 우아한 스와이프 및 키보드 상호작용
  • 브라우저의 URL 해시를 통한 딥 링크가 인페이지 스크롤 앵커링 및 공유 지원을 처리함
  • <a>id="#hash" 요소 마크업을 사용한 스크린 리더 지원
  • prefers-reduced-motion: 크로스페이드 전환과 즉각적인 인페이지 스크롤을 사용 설정합니다.
  • 선택한 탭에 동적으로 밑줄을 치고 색상을 변경하는 초안 @scroll-timeline 웹 기능

HTML

기본적으로 UX에서 링크를 클릭하고 URL이 중첩된 페이지 상태를 나타내도록 한 다음 브라우저에서 일치하는 요소로 스크롤할 때 콘텐츠 영역이 업데이트됩니다.

여기에는 구조적 콘텐츠 멤버인 링크와 :target가 있습니다. <nav>가 적합한 링크 목록과 <section>가 적합한 <article> 요소 목록이 필요합니다. 각 링크 해시는 섹션과 일치하므로 브라우저에서 앵커링을 통해 스크롤할 수 있습니다.

링크 버튼을 클릭하여 포커스가 맞춰진 콘텐츠 슬라이딩

예를 들어 링크를 클릭하면 Chrome 89의 :target 도움말로 자동 이동되며 자바스크립트가 필요하지 않습니다. 그러면 사용자는 평소대로 입력 장치를 사용하여 기사 콘텐츠를 스크롤할 수 있습니다. 마크업에 표시된 대로 무료 콘텐츠입니다.

다음 마크업을 사용하여 탭을 구성했습니다.

<snap-tabs>
  <header>
    <nav>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
    </nav>
  </header>
  <section>
    <article></article>
    <article></article>
    <article></article>
    <article></article>
  </section>
</snap-tabs>

다음과 같이 hrefid 속성을 사용하여 <a><article> 요소 간의 연결을 설정할 수 있습니다.

<snap-tabs>
  <header>
    <nav>
      <a href="#responsive"></a>
      <a href="#accessible"></a>
      <a href="#overscroll"></a>
      <a href="#more"></a>
    </nav>
  </header>
  <section>
    <article id="responsive"></article>
    <article id="accessible"></article>
    <article id="overscroll"></article>
    <article id="more"></article>
  </section>
</snap-tabs>

그런 다음 기사에 lorem을 혼합하고 긴 길이와 이미지 세트를 혼합하여 링크를 채웠습니다. 작업할 콘텐츠로 레이아웃을 시작할 수 있습니다.

스크롤 레이아웃

이 구성요소에는 세 가지 유형의 스크롤 영역이 있습니다.

  • 탐색 창(분홍색)을 가로로 스크롤할 수 있음
  • 콘텐츠 영역(파란색)을 가로로 스크롤할 수 있음
  • 각 기사 항목(녹색)은 세로로 스크롤할 수 있습니다.
다채로운 색상의 상자 3개에 색상 일치 화살표가 표시되어 있습니다. 이 상자는 스크롤 영역의 윤곽을 잡고 스크롤 방향을 보여줍니다.

스크롤과 관련된 두 가지 유형의 요소가 있습니다.


  1. overflow 속성 스타일을 가진 정의된 측정기준이 있는 상자입니다.
  2. 대형 표면
    이 레이아웃에서는 목록 컨테이너(탐색 링크, 섹션 기사, 기사 콘텐츠)입니다.

<snap-tabs> 레이아웃

선택한 최상위 수준 레이아웃은 Flex (Flexbox)였습니다. 방향을 column로 설정했으므로 헤더와 섹션이 세로로 정렬됩니다. 이는 첫 번째 스크롤 창이며, 오버플로가 숨겨진 모든 항목을 숨깁니다. 헤더와 섹션은 곧 개별 영역으로 오버스크롤을 사용합니다.

HTML
<snap-tabs>
  <header></header>
  <section></section>
</snap-tabs>
CSS
  snap-tabs {
  display: flex;
  flex-direction: column;

  /* establish primary containing box */
  overflow: hidden;
  position: relative;

  & > section {
    /* be pushy about consuming all space */
    block-size: 100%;
  }

  & > header {
    /* defend against 
needing 100% */ flex-shrink: 0; /* fixes cross browser quarks */ min-block-size: fit-content; } }

다채로운 색상의 3스크롤 다이어그램을 다시 가리키기

  • 이제 <header>(분홍색) 스크롤 컨테이너가 될 준비가 되었습니다.
  • <section>(파란색) 스크롤 컨테이너로 준비됩니다.

아래에 VisBug와 함께 강조 표시한 프레임을 사용하면 스크롤 컨테이너가 만든 을 확인할 수 있습니다.

헤더와 섹션 요소에 핫핑크 오버레이가 있어서 구성요소에서 차지하는 공간을 알 수 있습니다.

<header> 레이아웃

다음 레이아웃은 거의 동일합니다. Flex를 사용하여 세로 순서를 생성합니다.

HTML
<snap-tabs>
  <header>
    <nav></nav>
    <span class="snap-indicator"></span>
  </header>
  <section></section>
</snap-tabs>
CSS
header {
  display: flex;
  flex-direction: column;
}

.snap-indicator는 링크 그룹과 함께 가로로 이동해야 하며 이 헤더 레이아웃은 이 단계를 설정하는 데 도움이 됩니다. 여기에는 절대 위치로 배치된 요소가 없습니다.

nav 및 span.indicator 요소에 핫핑크 오버레이가 있어서 구성요소에서 차지하는 공간을 대략적으로 보여줍니다.

다음은 스크롤 스타일입니다. 두 개의 가로 스크롤 영역 (헤더 및 섹션) 간에 스크롤 스타일을 공유할 수 있으므로 유틸리티 클래스 .scroll-snap-x를 만들었습니다.

.scroll-snap-x {
  /* browser decide if x is ok to scroll and show bars on, y hidden */
  overflow: auto hidden;
  /* prevent scroll chaining on x scroll */
  overscroll-behavior-x: contain;
  /* scrolling should snap children on x */
  scroll-snap-type: x mandatory;

  @media (hover: none) {
    scrollbar-width: none;

    &::-webkit-scrollbar {
      width: 0;
      height: 0;
    }
  }
}

각각은 x축의 오버플로우, 오버스크롤 트랩을 위한 스크롤 포함, 터치 기기의 숨겨진 스크롤바, 마지막으로 콘텐츠 프레젠테이션 영역을 잠그기 위한 스크롤 스냅이 필요합니다. 키보드 탭 순서에 액세스할 수 있으며 모든 상호작용 가이드가 자연스럽게 초점을 맞춥니다. 스크롤 스냅 컨테이너도 키보드에서 캐러셀 스타일로 상호작용합니다.

탭 헤더 <nav> 레이아웃

탐색 링크는 줄바꿈 없이 한 줄로 배치하고 세로로 가운데 정렬해야 하며 각 링크 항목은 스크롤-스냅 컨테이너에 맞춰야 합니다. 2021년 CSS도 훌륭하게 구성되었습니다.

HTML
<nav>
  <a></a>
  <a></a>
  <a></a>
  <a></a>
</nav>
CSS
  nav {
  display: flex;

  & a {
    scroll-snap-align: start;

    display: inline-flex;
    align-items: center;
    white-space: nowrap;
  }
}

각 링크 스타일과 크기 자체가 조정되므로 탐색 레이아웃에서는 방향과 흐름만 지정하면 됩니다. 탐색 항목의 고유한 너비를 사용하면 표시기가 너비를 새 타겟에 맞춰 조정하므로 탭 간 전환이 재미있어집니다. 여기에 포함된 요소 수에 따라 브라우저가 스크롤바를 렌더링하거나 렌더링하지 않습니다.

탐색의 a 요소에는 핫핑크 오버레이가 있어, 구성요소에서 차지하는 공간 및 오버플로우 위치를 표시합니다.

<section> 레이아웃

이 섹션은 유연한 항목이며 공간을 가장 많이 소비해야 합니다. 또한 기사를 배치할 열을 만들어야 합니다. CSS 2021에서도 신속하게 대응하시기 바랍니다. block-size: 100%는 이 요소를 확장하여 상위 요소를 최대한 채운 다음 자체 레이아웃의 경우 상위 요소의 너비가 100%인 일련의 열을 만듭니다. 여기서는 상위 항목에 강력한 제약 조건을 작성했기 때문에 백분율이 효과적입니다.

HTML
<section>
  <article></article>
  <article></article>
  <article></article>
  <article></article>
</section>
CSS
  section {
  block-size: 100%;

  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
}

마치 '최대한 세로로 밀면서'라고 말하는 것과 같습니다(flex-shrink: 0로 설정한 헤더: 이 확장 푸시를 방지하는 방어임). 그러면 전체 높이 열 집합의 행 높이를 설정합니다. auto-flow 스타일은 그리드에 항상 원하는 대로 정확히 원하는 대로 하위 요소를 가로선에 배치하도록(줄바꿈 없이) 상위 창을 오버플로하도록 지시합니다.

기사 요소에 핫핑크 오버레이가 있어, 구성요소에서 차지하는 공간과 넘쳐나는 위치를 대략적으로 보여줍니다.

가끔 문제가 복잡해질 때가 있어요! 이 섹션 요소는 상자에 맞지만 상자 집합을 만들기도 합니다. 시각적 요소와 설명이 도움이 되었길 바랍니다.

<article> 레이아웃

사용자는 기사 콘텐츠를 스크롤할 수 있어야 하며 스크롤바는 오버플로가 있는 경우에만 표시되어야 합니다. 이러한 기사 요소가 깔끔하게 배치되어 있습니다. 두 요소는 동시에 스크롤 상위 요소와 스크롤 하위 요소입니다. 이 경우 브라우저는 실제로 까다로운 터치, 마우스 및 키보드 상호작용을 처리합니다.

HTML
<article>
  <h2></h2>
  <p></p>
  <p></p>
  <h2></h2>
  <p></p>
  <p></p>
  ...
</article>
CSS
article {
  scroll-snap-align: start;

  overflow-y: auto;
  overscroll-behavior-y: contain;
}

상위 스크롤러 내에서 기사가 스냅되도록 선택했습니다. 탐색 링크 항목과 기사 요소가 각 스크롤 컨테이너의 인라인 시작에 맞춰지는 방식이 정말 마음에 듭니다. 그것은 조화로운 관계처럼 보이고 느껴집니다.

기사 요소와 그 하위 요소에는 핫핑크 오버레이가 있어, 구성요소에서 차지하는 공간과 넘침하는 방향을 대략적으로 표시합니다.

기사는 그리드 하위 요소이며 크기는 스크롤 UX를 제공하려는 표시 영역 영역으로 미리 결정됩니다. 즉, 여기에는 높이 또는 너비 스타일이 필요하지 않으며 오버플로 방식만 정의하면 됩니다. overflow-y를 auto로 설정한 다음 편리한 오버스크롤 동작 속성으로 스크롤 상호작용도 트랩합니다.

스크롤 영역 3개 요약

시스템 설정에서 '항상 스크롤바를 표시'하도록 선택했습니다. 레이아웃과 스크롤 조정을 검토해야 하므로 이 설정이 켜져 있는 상태에서 레이아웃이 작동하는 것이 더 중요하다고 생각합니다.

스크롤바 3개가 표시되도록 설정되어 이제 레이아웃 공간을 차지하지만 구성요소는 여전히 멋지게 보입니다.

이 구성요소의 스크롤바 여백을 보면 스크롤 영역의 위치, 스크롤 영역이 지원하는 방향, 서로 상호작용하는 방식을 명확하게 표시하는 데 도움이 됩니다. 이러한 각 스크롤 창 프레임이 어떻게 레이아웃의 플렉스 또는 그리드 상위 요소인지 고려하세요.

DevTools는 이를 시각화하는 데 도움을 줄 수 있습니다.

스크롤 영역에는 그리드 및 플렉스박스 도구 오버레이가 있어 구성요소에서 차지하는 공간과 오버랩되는 방향을 대략적으로 표시합니다.
앵커 요소로 가득 찬 Flexbox 탐색 요소 레이아웃, 기사 요소로 가득 찬 그리드 섹션 레이아웃, 단락과 제목 요소로 가득한 기사 요소를 보여주는 Chromium Devtools.

스크롤 레이아웃이 완성되었습니다. 맞추기, 딥 링크 가능, 키보드 액세스가 가능합니다. UX 개선, 스타일, 즐거움을 위한 튼튼한 기반

주요 기능

스크롤 스냅된 하위 요소는 크기 조절 중에 고정된 위치를 유지합니다. 즉, JavaScript는 기기 회전이나 브라우저 크기 조절 시 아무것도 표시할 필요가 없습니다. Chromium DevTools 기기 모드에서 반응형 이외의 모드를 선택한 다음 기기 프레임의 크기를 조절해 사용해 보세요. 요소가 뷰에 유지되며 콘텐츠와 함께 잠겨 있습니다. 이 기능은 Chromium이 사양과 일치하도록 구현을 업데이트한 이후 사용할 수 있습니다. 자세한 내용은 블로그 게시물을 참조하세요.

애니메이션

여기서 애니메이션 작업의 목표는 상호작용을 UI 의견과 명확하게 연결하는 것입니다. 이렇게 하면 사용자가 모든 콘텐츠를 원활하게 검색할 수 있도록 안내하거나 지원할 수 있습니다. 목적에 맞게 모션을 조건부로 추가하겠습니다. 이제 사용자가 운영체제에서 모션 환경설정을 지정할 수 있으므로 인터페이스에서 사용자의 환경설정에 응답하는 것이 즐거워집니다.

탭 밑줄을 기사 스크롤 위치에 연결하겠습니다. 맞추기는 멋진 정렬일 뿐만 아니라 애니메이션의 시작과 끝을 고정하는 역할도 합니다. 이렇게 하면 미니 지도처럼 작동하는 <nav>가 콘텐츠에 연결된 상태로 유지됩니다. CSS와 JS 모두에서 사용자의 모션 환경설정을 확인할 예정입니다. 배려할 만한 멋진 장소가 몇 군데 있습니다!

스크롤 동작

:targetelement.scrollIntoView()의 모션 동작을 모두 개선할 수 있습니다. 기본적으로 즉시 반영됩니다. 브라우저는 스크롤 위치만 설정합니다. 스크롤 위치를 깜박이지 않고 스크롤 위치로 전환하려면 어떻게 해야 할까요?

@media (prefers-reduced-motion: no-preference) {
  .scroll-snap-x {
    scroll-behavior: smooth;
  }
}

여기서는 모션과 스크롤처럼 사용자가 제어할 수 없는 모션을 도입하므로 사용자가 운영체제에서 감소된 모션을 선호하지 않는 경우에만 이 스타일을 적용합니다. 이런 식으로 스크롤 모션에 문제가 없는 분들을 위해서만 스크롤 모션을 소개합니다

탭 표시기

이 애니메이션의 목적은 표시기를 콘텐츠 상태와 연결하는 데 도움이 됩니다. 움직임을 줄이고 싶은 사용자에게는 border-bottom 스타일의 색상을 크로스페이드하고, 모션에 문제가 없는 사용자에게는 스크롤 링크 슬라이딩 + 색상 페이드 애니메이션을 사용하기로 결정했습니다.

Chromium Devtools에서 환경설정을 전환하여 두 가지 전환 스타일을 시연할 수 있습니다. 이걸 만드는 과정이 굉장히 즐거웠습니다.

@media (prefers-reduced-motion: reduce) {
  snap-tabs > header a {
    border-block-end: var(--indicator-size) solid hsl(var(--accent) / 0%);
    transition: color .7s ease, border-color .5s ease;

    &:is(:target,:active,[active]) {
      color: var(--text-active-color);
      border-block-end-color: hsl(var(--accent));
    }
  }

  snap-tabs .snap-indicator {
    visibility: hidden;
  }
}

사용자가 감소된 모션을 선호하면 더 이상 필요하지 않으므로 .snap-indicator를 숨깁니다. 그런 다음 border-block-end 스타일과 transition로 바꿉니다. 또한 탭 상호작용에서 활성 탐색 항목에 브랜드 밑줄 강조 표시뿐만 아니라 텍스트 색상도 더 어두워집니다. 활성 요소는 텍스트 색상 대비가 높고 밝은 언더라이트 강조가 있습니다.

사용자의 모션 환경설정을 신중하게 준수한다는 의미에서 CSS를 몇 줄만 더 추가하여 사용자가 있다는 느낌을 줄 수 있습니다. 나는 그것을 사랑합니다.

@scroll-timeline

위 섹션에서는 감소된 모션 크로스페이드 스타일을 처리하는 방법을 살펴보았고, 이 섹션에서는 표시기와 스크롤 영역을 함께 연결한 방법을 보여드리겠습니다. 다음은 재미있는 실험 기능입니다. 여러분도 저처럼 흥분하셨기를 바랍니다.

const { matches:motionOK } = window.matchMedia(
  '(prefers-reduced-motion: no-preference)'
);

먼저 JavaScript에서 사용자의 모션 환경설정을 확인합니다. 그 결과가 false이고 사용자가 줄어든 모션을 선호한다는 의미라면 스크롤 연결 모션 효과를 실행하지 않습니다.

if (motionOK) {
  // motion based animation code
}

이 문서 작성 시점을 기준으로 @scroll-timeline의 브라우저 지원은 없습니다. 실험용 구현만 포함된 초안 사양입니다. 하지만 이 데모에서 사용하는 폴리필이 있습니다.

ScrollTimeline

CSS와 JavaScript 모두 스크롤 타임라인을 만들 수 있지만, 애니메이션에 실시간 요소 측정을 사용할 수 있도록 JavaScript를 선택했습니다.

const sectionScrollTimeline = new ScrollTimeline({
  scrollSource: tabsection,  // snap-tabs > section
  orientation: 'inline',     // scroll in the direction letters flow
  fill: 'both',              // bi-directional linking
});

한 항목이 다른 항목의 스크롤 위치를 따라가기를 원하고 ScrollTimeline를 만들어 스크롤 링크의 드라이버인 scrollSource를 정의합니다. 일반적으로 웹의 애니메이션은 전역 시간 틱을 기준으로 실행되지만 메모리의 맞춤 sectionScrollTimeline를 사용하면 이를 모두 변경할 수 있습니다.

tabindicator.animate({
    transform: ...,
    width: ...,
  }, {
    duration: 1000,
    fill: 'both',
    timeline: sectionScrollTimeline,
  }
);

애니메이션의 키프레임을 살펴보기 전에 스크롤의 팔로어인 tabindicator가 섹션의 스크롤인 맞춤 타임라인에 따라 애니메이션 처리됩니다. 이렇게 하면 연결이 완료되지만 애니메이션화할 최종 요소인 스테이트풀(Stateful) 포인트(키프레임이라고도 함)가 누락되었습니다.

동적 키프레임

@scroll-timeline로 애니메이션을 적용하는 매우 강력한 순수 선언적 CSS 방법이 있지만, 제가 선택한 애니메이션은 너무 동적입니다. auto 너비 간에 전환하는 방법은 없으며 하위 요소 길이를 기반으로 여러 키프레임을 동적으로 만들 수 없습니다.

JavaScript는 이 정보를 얻는 방법을 알고 있으므로 하위 요소를 직접 반복하고 런타임 시 계산된 값을 가져옵니다.

tabindicator.animate({
    transform: [...tabnavitems].map(({offsetLeft}) =>
      `translateX(${offsetLeft}px)`),
    width: [...tabnavitems].map(({offsetWidth}) =>
      `${offsetWidth}px`)
  }, {
    duration: 1000,
    fill: 'both',
    timeline: sectionScrollTimeline,
  }
);

tabnavitem의 경우 offsetLeft 위치의 구조를 해체하고 이를 translateX 값으로 사용하는 문자열을 반환합니다. 그러면 애니메이션의 변환 키프레임 4개가 생성됩니다. 너비도 마찬가지입니다. 각각에 동적 너비를 요청한 다음 키프레임 값으로 사용됩니다.

다음은 내 글꼴 및 브라우저 환경설정을 기준으로 한 출력 예입니다.

TranslateX 키프레임:

[...tabnavitems].map(({offsetLeft}) =>
  `translateX(${offsetLeft}px)`)

// results in 4 array items, which represent 4 keyframe states
// ["translateX(0px)", "translateX(121px)", "translateX(238px)", "translateX(464px)"]

너비 키프레임:

[...tabnavitems].map(({offsetWidth}) =>
  `${offsetWidth}px`)

// results in 4 array items, which represent 4 keyframe states
// ["121px", "117px", "226px", "67px"]

전략을 요약하기 위해 이제 탭 표시기가 섹션 스크롤러의 스크롤 맞추기 위치에 따라 4개의 키프레임에서 애니메이션 처리됩니다. 맞추기 지점은 키프레임 사이에 명확한 묘사를 만들고 애니메이션의 동기화된 느낌을 더해줍니다.

활성 탭과 비활성 탭은 VisBug 오버레이와 함께 표시되고,

사용자는 상호작용과 함께 애니메이션을 구동하여 표시기의 너비와 위치가 한 섹션에서 다음 섹션으로 변경되는 것을 확인하고 스크롤로 완벽하게 추적합니다.

눈치채지 못했을 수도 있지만, 강조 표시된 탐색 항목이 선택될 때 색상이 전환된다는 점이 무척 자랑스럽습니다.

강조 표시된 항목의 대비가 높을수록 선택 해제된 연한 회색이 더 뒤로 푸시백됩니다. 마우스 오버 시 및 선택 시와 같이 텍스트의 색상을 전환하는 것이 일반적이지만, 다음 단계는 밑줄 표시기와 동기화되어 스크롤 시 색상을 전환하는 것입니다.

방법은 다음과 같습니다.

tabnavitems.forEach(navitem => {
  navitem.animate({
      color: [...tabnavitems].map(item =>
        item === navitem
          ? `var(--text-active-color)`
          : `var(--text-color)`)
    }, {
      duration: 1000,
      fill: 'both',
      timeline: sectionScrollTimeline,
    }
  );
});

각 탭 탐색 링크에는 밑줄 표시기와 동일한 스크롤 타임라인을 추적하는 이 새로운 색상 애니메이션이 필요합니다. 이전과 동일한 타임라인을 사용합니다. 스크롤 시 틱을 내보내는 것이기 때문에 원하는 모든 유형의 애니메이션에서 이 틱을 사용할 수 있습니다. 앞서 했던 것처럼 루프에 4개의 키프레임을 만들고 색상을 반환합니다.

[...tabnavitems].map(item =>
  item === navitem
    ? `var(--text-active-color)`
    : `var(--text-color)`)

// results in 4 array items, which represent 4 keyframe states
// [
  "var(--text-active-color)",
  "var(--text-color)",
  "var(--text-color)",
  "var(--text-color)",
]

var(--text-active-color) 색상의 키프레임은 링크를 강조 표시하고, 그렇지 않으면 표준 텍스트 색상으로 강조 표시합니다. 외부 루프는 각 탐색 항목이고 내부 루프는 각 navitem의 개인 키프레임이므로 중첩 루프는 비교적 직관적입니다. 외부 루프 요소가 내부 루프 요소와 동일한지 확인하고 이를 사용하여 선택 시점을 확인합니다.

이 글을 쓰는 것이 정말 즐거웠습니다. 최고죠.

훨씬 더 많은 자바스크립트 개선사항

여기서 보여 드리는 핵심 내용은 JavaScript 없이도 작동합니다. 이제 JS를 사용할 수 있을 때 어떻게 개선할 수 있는지 살펴보겠습니다.

딥 링크는 모바일 용어에 더 가깝습니다. 하지만 딥 링크의 의도는 탭 콘텐츠로 연결되는 URL을 직접 공유할 수 있다는 점에서 탭이라고 생각합니다. 브라우저는 URL 해시에서 일치하는 ID로 인페이지로 이동합니다. 이 onload 핸들러가 여러 플랫폼에 영향을 미치는 것을 발견했습니다.

window.onload = () => {
  if (location.hash) {
    tabsection.scrollLeft = document
      .querySelector(location.hash)
      .offsetLeft;
  }
}

스크롤 종료 동기화

사용자가 항상 키보드를 클릭하거나 사용하지는 않으며, 때로는 가능한 한 자유롭게 스크롤할 수도 있습니다. 섹션 스크롤러가 스크롤을 멈추면 상단 탐색 메뉴에서 스크롤되는 위치와 일치해야 합니다.

스크롤 끝을 기다리는 방법은 다음과 같습니다. js tabsection.addEventListener('scroll', () => { clearTimeout(tabsection.scrollEndTimer); tabsection.scrollEndTimer = setTimeout(determineActiveTabSection, 100); });

섹션을 스크롤할 때마다 섹션 제한시간을 지우고 새 제한 시간을 시작합니다. 섹션 스크롤이 중지되면 시간 제한을 삭제하지 말고 휴식 후 100ms를 실행합니다. 이벤트가 실행되면 사용자가 중지한 위치를 파악하는 함수를 호출합니다.

const determineActiveTabSection = () => {
  const i = tabsection.scrollLeft / tabsection.clientWidth;
  const matchingNavItem = tabnavitems[i];

  matchingNavItem && setActiveTab(matchingNavItem);
};

스크롤이 맞춰졌다고 가정할 때 현재 스크롤 위치를 스크롤 영역의 너비로 나누면 소수점이 아닌 정수가 됩니다. 그런 다음 계산된 색인을 통해 캐시에서 navitem을 가져오려고 합니다. 그런 다음 무언가를 찾으면 일치 항목을 활성으로 설정합니다.

const setActiveTab = tabbtn => {
  tabnav
    .querySelector(':scope a[active]')
    .removeAttribute('active');

  tabbtn.setAttribute('active', '');
  tabbtn.scrollIntoView();
};

활성 탭을 설정하려면 먼저 현재 활성 탭을 지운 다음 수신되는 탐색 항목에 활성 상태 속성을 지정합니다. scrollIntoView() 호출은 주목할 만한 흥미로운 CSS 상호작용입니다.

.scroll-snap-x {
  overflow: auto hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;

  @media (prefers-reduced-motion: no-preference) {
    scroll-behavior: smooth;
  }
}

가로 스크롤 맞추기 유틸리티 CSS에서 사용자가 모션을 허용하는 경우 smooth 스크롤을 적용하는 미디어 쿼리를 중첩했습니다. JavaScript는 요소를 뷰로 스크롤하는 호출을 자유롭게 만들 수 있으며 CSS는 UX를 선언적으로 관리할 수 있습니다. 가끔씩 장난스럽게 작은 상대를 만들어 주기도 합니다.

결론

이제 내가 어떻게 했는지 알았으니 어떻게 할 건가요? 이렇게 하면 재미있는 구성요소 아키텍처가 만들어집니다. 누가 가장 좋아하는 프레임워크에 슬롯이 있는 첫 번째 버전을 만들까요? 🙂

접근 방식을 다양화하고 웹에서 빌드하는 모든 방법을 알아보겠습니다. Glitch를 만들고 내 버전을 트윗하면 아래 커뮤니티 리믹스 섹션에 추가합니다.

커뮤니티 리믹스