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-type | x/y mandatory | 항상 스냅 포인트에 정렬 |
| scroll-snap-type | x/y proximity | 가까울 때만 정렬 |
| scroll-snap-align | start/center/end | 정렬 기준점 |
| scroll-snap-stop | normal/always | 빠른 스크롤 시 통과 여부 |
| scroll-padding | 길이값 | 스냅 영역 패딩 |
| overscroll-behavior | contain/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