본문 바로가기
Frontend2026년 2월 5일7분 읽기

CSS Scroll Snap으로 네이티브 같은 캐러셀 만들기

YS
김영삼
조회 447

CSS Scroll Snap 소개

CSS Scroll Snap은 JavaScript 없이 스크롤 위치를 특정 지점에 자동으로 정렬(snap)하는 기능입니다. 캐러셀, 풀페이지 스크롤, 이미지 갤러리 등에 활용됩니다.

기본 수평 캐러셀

.carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  gap: 16px;
  padding: 16px;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.carousel::-webkit-scrollbar {
  display: none;
}

.carousel-item {
  flex: 0 0 80%;
  scroll-snap-align: center;
  border-radius: 12px;
  aspect-ratio: 16 / 9;
}

.carousel-item--full {
  flex: 0 0 100%;
  scroll-snap-align: start;
}

HTML 구조

<div class="carousel">
  <div class="carousel-item">
    <img src="/slide1.jpg" alt="슬라이드 1" />
  </div>
  <div class="carousel-item">
    <img src="/slide2.jpg" alt="슬라이드 2" />
  </div>
  <div class="carousel-item">
    <img src="/slide3.jpg" alt="슬라이드 3" />
  </div>
</div>

풀페이지 세로 스크롤

.fullpage {
  height: 100vh;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
}

.fullpage-section {
  height: 100vh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: flex;
  align-items: center;
  justify-content: center;
}

.fullpage-section:nth-child(1) { background: #1a1a2e; color: #fff; }
.fullpage-section:nth-child(2) { background: #16213e; color: #fff; }
.fullpage-section:nth-child(3) { background: #0f3460; color: #fff; }

이미지 갤러리

.gallery {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 300px;
  gap: 12px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  overscroll-behavior-x: contain;
  padding: 20px;
}

.gallery-item {
  scroll-snap-align: start;
  border-radius: 8px;
  overflow: hidden;
}

.gallery-item img {
  width: 100%;
  height: 200px;
  object-fit: cover;
  transition: transform 0.3s;
}

.gallery-item:hover img {
  transform: scale(1.05);
}

scroll-snap 속성 정리

속성설명
scroll-snap-typex/y mandatory항상 스냅 포인트에 정렬
scroll-snap-typex/y proximity가까울 때만 정렬
scroll-snap-alignstart/center/end정렬 기준점
scroll-snap-stopnormal/always빠른 스크롤 시 통과 여부
scroll-padding길이값스냅 영역 패딩
overscroll-behaviorcontain/none스크롤 전파 방지

JS 인디케이터 연동

const carousel = document.querySelector('.carousel');
const items = document.querySelectorAll('.carousel-item');
const dots = document.querySelectorAll('.dot');

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const index = [...items].indexOf(entry.target);
      dots.forEach((dot, i) => {
        dot.classList.toggle('active', i === index);
      });
    }
  });
}, {
  root: carousel,
  threshold: 0.5
});

items.forEach(item => observer.observe(item));

function goToSlide(index) {
  items[index].scrollIntoView({
    behavior: 'smooth',
    inline: 'center',
    block: 'nearest'
  });
}
  • CSS만으로 60fps 부드러운 스크롤 스냅 구현 가능
  • 모든 최신 브라우저에서 지원 (IE 제외)
  • scroll-snap-stop: always로 빠른 스와이프에서도 한 칸씩만 이동
  • overscroll-behavior-x: contain으로 가로 스크롤이 세로 스크롤에 영향 주지 않도록
  • 접근성을 위해 키보드 네비게이션과 ARIA 속성 추가 권장

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록