Lompat ke konten

Karosel geser

Untuk menawarkan beberapa hal berdampingan ketika tidak ada satu pun yang cukup penting untuk menguasai layar.

Media

Pratinjau langsung

Sumber

<section class="dc-car" aria-roledescription="캐러셀" aria-label="이번 주 추천">
  <div class="dc-car__track" tabindex="0" role="group" aria-label="추천 3개, 좌우로 넘겨 보기">
    <article class="dc-car__slide" id="dc-car-s1">
      <div class="dc-car__media" role="img" aria-label="비계 위에서 본 현장 전경"></div>
      <h3 class="dc-car__title">가을 자재 할인전</h3>
      <p class="dc-car__desc">9월 30일까지 · 최대 18%</p>
    </article>
    <article class="dc-car__slide" id="dc-car-s2">
      <div class="dc-car__media" role="img" aria-label="안전 교육장 사진"></div>
      <h3 class="dc-car__title">신규 입사자 안전 교육</h3>
      <p class="dc-car__desc">9월 15일 오전 9시 · 2공구 회의실</p>
    </article>
    <article class="dc-car__slide" id="dc-car-s3">
      <div class="dc-car__media" role="img" aria-label="타설 장비 사진"></div>
      <h3 class="dc-car__title">장비 대여 신청 열림</h3>
      <p class="dc-car__desc">다음 주 배차까지 신청 가능</p>
    </article>
  </div>
  <nav aria-label="슬라이드 이동">
    <ul class="dc-car__dots">
      <li><a class="dc-car__dot" href="#dc-car-s1" aria-current="true"><span class="dc-sr">1번 슬라이드 보기</span></a></li>
      <li><a class="dc-car__dot" href="#dc-car-s2"><span class="dc-sr">2번 슬라이드 보기</span></a></li>
      <li><a class="dc-car__dot" href="#dc-car-s3"><span class="dc-sr">3번 슬라이드 보기</span></a></li>
    </ul>
  </nav>
</section>
.dc-car {
  /* 사진 위에 올라가는 글자와 배지는 두 테마에서 같은 쪽이어야 한다. 스크림이
     밝은 모드에서도 어두우므로 글자는 늘 밝은 쪽, 배지 바탕은 늘 어두운 쪽이다.
     고정색을 적는 대신 토큰을 양쪽에서 뒤집어 그 두 값을 만든다. */
  --dc-on-media: var(--dc-text-on);
  --dc-media-ink: var(--dc-text);
  font-family: var(--dc-font);
}
@media (prefers-color-scheme: dark) {
  .dc-car {
    --dc-on-media: var(--dc-text);
    --dc-media-ink: var(--dc-text-on);
  }
}
.dc-car__track {
  display: flex;
  gap: var(--dc-3);
  padding: var(--dc-1) var(--dc-4) var(--dc-2);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-left: var(--dc-4);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.dc-car__track::-webkit-scrollbar { display: none; }
.dc-car__slide {
  position: relative;
  flex: 0 0 82%;
  display: flex;
  flex-direction: column;
  gap: var(--dc-2);
  padding: var(--dc-3);
  scroll-snap-align: start;
  background: var(--dc-surface);
  border: 1px solid var(--dc-line);
  border-radius: var(--dc-r-md);
  box-shadow: var(--dc-sh-1);
}
.dc-car__media {
  aspect-ratio: 16 / 10;
  border-radius: var(--dc-r-sm);
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--dc-brand) 32%, var(--dc-sunken)),
    var(--dc-sunken));
}
.dc-car__slide:nth-child(2) .dc-car__media {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--dc-info) 32%, var(--dc-sunken)),
    var(--dc-sunken));
}
.dc-car__slide:nth-child(3) .dc-car__media {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--dc-ok) 30%, var(--dc-sunken)),
    var(--dc-sunken));
}
.dc-car__title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--dc-text);
}
.dc-car__desc {
  font-size: 13px;
  line-height: 1.45;
  color: var(--dc-text-sub);
}
.dc-car__dots {
  display: flex;
  justify-content: center;
  align-items: center;
}
.dc-car__dot {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--dc-r-full);
  text-decoration: none;
}
.dc-car__dot::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: var(--dc-r-full);
  background: var(--dc-line-bold);
  transition: width var(--dc-slow), background var(--dc-slow);
}
.dc-car__dot[aria-current="true"]::before {
  width: 22px;
  background: var(--dc-brand);
}
.dc-car--full .dc-car__track { gap: 0; padding: 0; scroll-padding-left: 0; }
.dc-car--full .dc-car__slide {
  flex: 0 0 100%;
  gap: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.dc-car--full .dc-car__media { aspect-ratio: 3 / 2; border-radius: 0; }
.dc-car--full .dc-car__dots { margin-top: calc(-1 * var(--dc-7)); position: relative; }
.dc-car--full .dc-car__dot::before {
  background: color-mix(in srgb, var(--dc-on-media) 55%, transparent);
}
.dc-car--full .dc-car__dot[aria-current="true"]::before {
  background: var(--dc-on-media);
}
.dc-car__cap {
  position: absolute;
  inset: auto 0 0;
  display: grid;
  gap: var(--dc-1);
  padding: var(--dc-6) var(--dc-4) var(--dc-7);
  background: linear-gradient(to top,
    var(--dc-overlay),
    color-mix(in srgb, var(--dc-overlay) 45%, transparent) 45%,
    transparent);
}
.dc-car__cap .dc-car__title,
.dc-car__cap .dc-car__desc { color: var(--dc-on-media); }
.dc-car__count {
  position: absolute;
  top: var(--dc-4);
  right: var(--dc-4);
  padding: 2px var(--dc-2);
  border-radius: var(--dc-r-full);
  background: color-mix(in srgb, var(--dc-media-ink) 55%, transparent);
  color: var(--dc-on-media);
  font-size: 12px;
  font-weight: 700;
}

Cara memakainya

  • Biarkan kartu berikutnya mengintip, lebar sekitar 82% — kartu selebar layar menyembunyikan bahwa ini bisa digeser
  • Tiga sampai lima kartu. Lebih dari itu ujungnya tak pernah dilihat, ganti dengan daftar
  • Titik menunjukkan posisi; lewat enam slide, ganti titik dengan "2 dari 5"
  • Jangan berganti sendiri — konten yang bergerak saat dibaca harus dicari ulang

Hal yang perlu diwaspadai

  • Kalau titiknya bisa ditekan, area tekannya 44×44px meski titik yang terlihat tetap kecil
  • Tanpa tabindex="0" pada track, pengguna papan tik tak pernah sampai ke slide kedua
  • Titik tanpa nama slide membuat pembaca layar hanya menyebut beberapa gambar tanpa identitas

Berikutnya